Collect and Validate EU VAT Numbers
Selling to businesses in other EU countries means asking for a VAT number, checking it’s real, and leaving VAT off under the reverse charge. WooCommerce has no VAT number field, and charging VAT to a business that shouldn’t pay it means a refund and a corrected invoice later.
VAT Numbers adds a VAT number field to the Checkout block and the classic checkout and checks each number with VIES, the European Commission’s VAT number service. A valid business buyer in another EU country pays no VAT. The order keeps the number and the VIES result as proof, and the customer’s account remembers the number for next time.
Turn On VAT Numbers
- Open Stackless → Dashboard and turn on VAT Numbers.
- Go to Stackless → Settings → VAT Numbers, choose your settings and save.
The module pauses while WooCommerce EU VAT Number, EU VAT Assistant for WooCommerce or EU/UK VAT Validation Manager for WooCommerce is active, because they do the same job. The Dashboard says which plugin paused it.
Settings
- Field label: “VAT number” by default.
- Field: Optional (the default), or Required for EU billing addresses (business-only stores).
- VIES check: on by default. Turn it off to accept any number in the right format without asking VIES.
- Invalid numbers: Ask the customer to correct it (the default), or Accept the order and charge VAT.
- When VIES is down: Accept a well-formed number, remove VAT and check again later (the default), or Charge VAT until VIES confirms the number.
- Reverse charge: Remove VAT for valid business buyers in another EU country. On by default.
- Same country: Also remove VAT for buyers in your store’s own country. Off by default. It’s rarely correct, so ask your accountant first.
- Your VAT number: optional. Sent with each check so VIES returns a consultation number, the proof a tax office asks for.
The Field at Checkout
On the classic checkout, the field sits in the billing details after Company name. On the Checkout block, it sits in the address form, so totals update as the buyer types. When the order needs shipping, it shows in the shipping address too. Either way, the number is checked against the billing country.
Buyers can type the number with or without the country prefix. Spaces, dots, dashes and slashes are removed, and the billing country’s prefix is added when it’s missing. Greece uses EL in VIES, so a number typed with GR becomes EL. Signed-in customers find their last number filled in.
When a number can’t be accepted, checkout stops with one of these messages, using your field label:
- “This VAT number is not in the right format.”
- “This VAT number does not match your billing country.”
- “VIES does not recognize this VAT number. Check it, or leave the field empty to pay with VAT.” This one only shows with Ask the customer to correct it.
- “VAT number is required.” This one only shows with Required for EU billing addresses.
Who Pays VAT
| Buyer | Result |
|---|---|
| Valid number, billing address in another EU country | No VAT. The reverse charge applies. |
| Valid number, billing address in your store’s country | VAT is charged, unless Same country is on. |
| VIES doesn’t recognize the number | Checkout asks for a correction, or VAT is charged with Accept the order and charge VAT. |
| VIES is down, number in the right format | No VAT with the default setting, and the number is checked again later. VAT is charged with Charge VAT until VIES confirms the number. |
| VIES check is off, number in the right format | No VAT for another EU country. The order shows Not checked. |
| No number | VAT is charged as usual. |
| Billing address outside the EU and the United Kingdom | The number is saved on the order but not checked, and your normal tax settings apply. |
The reverse charge uses WooCommerce’s VAT exempt flag for the customer, so the order carries no tax at all, shipping included. If your prices include tax, WooCommerce takes the tax out of the price. The whole order is exempt; there’s no per-product exception.
When VIES Is Down
VIES asks each member state’s own system, and those go offline. A number VIES couldn’t check is marked on the order and checked again in the background, whichever fallback you chose:
- The first recheck runs an hour after the order, then every six hours, four tries in all.
- A valid answer adds a note that VIES confirmed the number.
- An invalid answer adds a note and flags the order: “Needs review: the number was not confirmed after checkout.”
- If VIES is still down after the last try, the order is flagged with a note asking you to check the number before you ship or file the return.
A recheck never changes the order’s totals. If VIES later rejects a number on an order that went through without VAT, you decide what to do about it.
Caching and Lookups
- Results are cached: a valid number for a week, an invalid or malformed one for a day, an outage for ten minutes. A buyer refreshing the checkout doesn’t ask VIES again.
- One visitor can check 12 new numbers an hour. After that, new numbers are treated as if VIES were down. Store managers aren’t limited.
- Each check waits up to eight seconds for VIES.
What the Order Keeps
On the order screen, under the billing address, you’ll see:
- The number and its result: Valid in VIES, Not valid in VIES, VIES was unavailable, Wrong format, Not checked or Other country.
- When it was checked, in UTC.
- The consultation number, when you set Your VAT number.
- The trader name VIES returned, when the member state shares it.
- Reverse charge applied (no VAT), when it was.
- Needs review, when a recheck didn’t confirm the number.
The trader address VIES returns is stored with the result too. Order emails show the number, and a reverse-charge order adds a VAT line: “Reverse charge: VAT to be accounted for by the recipient.”
Invoices and the Customer’s Account
A number that was valid, not checked, or entered while VIES was down is saved to the customer’s account and filled in at their next checkout. Changing the VAT number in the billing address under My Account updates it too.
When you create an invoice with Custom Invoices and pick that customer, the Tax / VAT number field fills in from their account.
Northern Ireland, Greece and Other Countries
- Northern Ireland: VIES checks Northern Ireland numbers with the XI prefix. Buyers there choose United Kingdom as the billing country and enter their XI number.
- Greece: VIES uses EL. A number typed with GR, or with no prefix, becomes EL.
- Great Britain: VIES doesn’t cover Great Britain, so a GB number (or a number typed without a prefix) for a United Kingdom billing address is saved on the order without a check. It never removes VAT; your tax settings decide what’s charged. Required for EU billing addresses doesn’t apply to United Kingdom addresses.
- Switzerland, Norway and other countries outside VIES: the number is saved on the order but not checked, and never removes VAT. The order screen shows it as Wrong format, because VIES can’t check it.
Privacy
Each check sends the VAT number, and your own VAT number when you set one, to the European Commission’s VIES service. The number, the VIES result, the trader name and address VIES returns, and the consultation number are stored on the order. The number is also saved on the customer’s account.
Tools → Export Personal Data includes the VAT number saved on the account and the number and VIES result on each order. Tools → Erase Personal Data always removes the number saved on the account.
The number on an order belongs to its VAT invoice, which tax law usually makes you keep. It’s erased only when WooCommerce removes that order’s personal data (WooCommerce → Settings → Accounts & Privacy, “Remove personal data from orders on request”). The order then keeps the VIES result, country and check time, and the reverse charge flag, so the invoice still shows why no VAT was charged.
Limits
- VIES covers EU countries and Northern Ireland only. Other numbers are saved but not checked or zero-rated.
- Great Britain numbers are saved but never checked, and they never remove VAT.
- The field shows on every billing address, whatever the country.
- The reverse charge applies to the whole order and every product in it.
- A recheck after an outage only adds notes and flags. It never changes totals or charges the buyer.
For Developers
stackless_vat_numbers_pre_check skips the VIES request. Return an array with status (valid, invalid, unavailable or format), name, address, request_date, request_identifier and error, or null to ask VIES:
add_filter('stackless_vat_numbers_pre_check', function ($result, $prefix, $number) {
if ($prefix === 'DE' && $number === '123456789') {
return ['status' => 'valid', 'name' => 'Test GmbH', 'address' => '', 'request_date' => '', 'request_identifier' => '', 'error' => ''];
}
return $result;
}, 10, 3);
Orders keep _stackless_vat_number, _stackless_vat_validation (the VIES result), _stackless_vat_reverse_charge and _stackless_vat_review. The account’s number is in the stackless_vat_number user meta.