Get a free API key on RapidAPI →
If you sell B2B across an EU border (or between the UK and the EU), you can usually zero-rate the sale under the reverse-charge mechanism — but only if your customer is genuinely VAT-registered. Tax authorities are blunt about this: if the number on the invoice turns out to be invalid or deregistered, the seller is typically liable for the missing VAT, plus interest. A regex check on the format does not protect you, because a syntactically perfect number can belong to a company that deregistered two years ago, or to nobody at all.
So real validation has two layers: format and check-digit validation (is this string even a possible German VAT number?) and registry validation (is it actually registered right now, and to whom?). The first is instant and offline; the second requires querying EU VIES for the 27 member states and HMRC for UK numbers — two different services with different formats and different failure modes. This article walks through doing both with the VAT Number Validator API.
Start with the cheap check. Most VAT number problems are simply typos made at checkout, and most countries embed a check digit that exposes them without any network round-trip to a registry:
GET /validate?vat=DE136695976&country=DE
The response tells you whether the number matches the country's format and whether its check digits are consistent — the German algorithm differs from the Italian one, which differs from the Irish one, and the API knows all of them, including Great Britain (GB) and Northern Ireland (XI). If valid comes back false here, don't bother calling the registry: show the user an inline error and let them fix the digit they fat-fingered. This is the check you want wired into your checkout form's blur event, because it's fast enough to run on every keystroke pause.
The API is tolerant of how humans actually type these numbers — DE 136 695 976, lowercase prefixes, dots and dashes all normalize to the same number — so you don't need to pre-clean input yourself.
Format-valid is necessary but not sufficient. Before you commit to zero-rating, hit the live registry:
GET /lookup?vat=DE136695976&country=DE
This queries VIES for EU numbers and HMRC for GB numbers, and returns whether the number is currently registered along with the registered company name and address. Compare that name against what your customer entered — a valid number attached to a completely different company is a classic fraud signal (someone pasting a number they found on a random invoice).
Store the whole lookup response with the order. If a tax authority later questions the zero-rating, a timestamped registry confirmation showing the number, name, and address at the time of sale is exactly the evidence you want to produce.
The numbers already in your CRM are usually the worst ones — collected over years, never verified. Send them to /validate-batch in one call and you get a per-number result, so you can flag every account that needs a corrected number before the next invoicing run instead of discovering them one bounced invoice at a time.
Which countries are supported? All 27 EU member states, Great Britain, and Northern Ireland. Call /countries for the current list with each country's expected format.
Do I need separate VIES and HMRC integrations? No — that's the point. One request format, one response shape, routed to the correct official registry.
Is the data scraped or cached? Neither. Lookups go straight to the official registries at request time, so a "registered" answer reflects the registry right now.
Calling vat-number-validator-eu-uk.p.rapidapi.com — replace YOUR_RAPIDAPI_KEY with your key.
curl --request GET \
--url 'https://vat-number-validator-eu-uk.p.rapidapi.com/validate?vat=DE136695976&country=DE' \
--header 'X-RapidAPI-Key: YOUR_RAPIDAPI_KEY' \
--header 'X-RapidAPI-Host: vat-number-validator-eu-uk.p.rapidapi.com'
import requests
url = "https://vat-number-validator-eu-uk.p.rapidapi.com/validate"
querystring = {"vat": "DE136695976", "country": "DE"}
headers = {
"X-RapidAPI-Key": "YOUR_RAPIDAPI_KEY",
"X-RapidAPI-Host": "vat-number-validator-eu-uk.p.rapidapi.com",
}
response = requests.get(url, headers=headers, params=querystring)
print(response.json())
const url = 'https://vat-number-validator-eu-uk.p.rapidapi.com/validate?vat=DE136695976&country=DE';
const options = {
method: 'GET',
headers: {
'X-RapidAPI-Key': 'YOUR_RAPIDAPI_KEY',
'X-RapidAPI-Host': 'vat-number-validator-eu-uk.p.rapidapi.com',
},
};
const response = await fetch(url, options);
console.log(await response.json());
import axios from 'axios';
const options = {
method: 'GET',
url: 'https://vat-number-validator-eu-uk.p.rapidapi.com/validate',
params: {vat: 'DE136695976', country: 'DE'},
headers: {
'X-RapidAPI-Key': 'YOUR_RAPIDAPI_KEY',
'X-RapidAPI-Host': 'vat-number-validator-eu-uk.p.rapidapi.com',
},
};
const { data } = await axios.request(options);
console.log(data);
Powered by the VAT Number Validator (EU & UK) API on RapidAPI.