Validate EU VAT numbers.
Even when VIES is down.
Numbers we know come back instantly. New ones race VIES REST, VIES SOAP, the Belgian KBO and two fallback providers in parallel, and you get the first definitive answer. Free.
- up to 5 sources in parallel
- first definitive answer wins
- instant answers for known numbers
- every source reported
Check a number now
No signup needed
How it works
A race, not a queue
Calling VIES alone means you inherit its bad days. Trying fallbacks one after another means every failure costs a timeout. Racing removes both problems.
-
VIES (REST)
Can confirm valid and invalidVIES (REST): busy (MS_MAX_CONCURRENT_REQ), finished after the response. -
VIES (SOAP)
Can confirm valid and invalidVIES (SOAP): valid · first definitive answer. -
KBO Public Search
Can only confirm validKBO Public Search: valid · confirms, finished after the response. -
vatcomply
Can confirm valid and invalidvatcomply: valid · agrees, finished after the response. -
controleerbtwnummer.eu
Can only confirm validcontroleerbtwnummer.eu: valid · agrees, finished after the response. -
KBO open data
Register lookup, no VAT verdictKBO open data: found · adds register details.
-
t = 0
Everything starts at once
VIES REST, VIES SOAP, the KBO (for Belgian numbers), vatcomply and controleerbtwnummer.eu are called in parallel. No waiting for one to time out before trying the next.
-
first
The first definitive answer wins
As soon as one source can decide, you get the response. A source that can only confirm valid numbers is never allowed to call a number invalid.
-
after
The rest keep working
Slower sources finish in the background. Their answers fill in names and addresses, and verify the verdict. Disagreements are flagged as conflict.
-
cached
Instant on repeat
Numbers checked before are answered from storage straight away, with the source and date. Older than 24 hours? You still get it instantly, flagged stale, while a fresh race runs in the background.
Sources
Every source, one answer, full transparency.
Every response lists what each source did: answered, failed with which error, skipped and why, or still running when we answered you. No black box.
All about the sources-
VIES (REST)
vies_rest
Can confirm valid and invalidVIES is the European Commission's VAT Information Exchange System. It does not hold data itself: it forwards each question to the national tax administration of the member state, live.
-
VIES (SOAP)
vies_soap
Can confirm valid and invalidThe same VIES service through its older SOAP interface. Because it is a separate endpoint, it sometimes answers while the REST one reports errors, and the other way around.
-
KBO Public Search
kbo_ws
Can only confirm valid Belgium onlyThe web service of the Crossroads Bank for Enterprises, the official Belgian business registry. It confirms whether an enterprise has an active VAT liability.
-
vatcomply
vatcomply
Can confirm valid and invalid VIES wrapperA free third-party API that queries VIES on its own infrastructure, with its own caching.
-
controleerbtwnummer.eu
controleerbtwnummer
Can only confirm validA third-party validation service. We only use it to confirm valid numbers.
-
KBO open data
kbo_open_data
Register lookup, no VAT verdict Belgium onlyThe open data extract of the Belgian business registry (KBO/BCE). We import it into our own database every day around 07:00 Brussels time, so it never depends on a remote service.
Developer experience
One GET request
Bearer token, JSON back. Messy input like BE 0684.579.082 is fine. Errors always have the same shape, rate limits come with headers.
validistrue,falseornull, never a guessserved_fromsays live, cache or stale cachesources[]shows every lane of the race- OpenAPI 3.1 spec at /openapi.json
curl -H "Authorization: Bearer $VAT_API_KEY" \
"https://vatapi.be/api/v1/vat/BE0684579082"
use Illuminate\Support\Facades\Http;
$vatNumber = 'BE0684579082';
// Throws on 4xx/5xx. On 429, wait the seconds in the Retry-After header.
$result = Http::withToken(config('services.vat_api.key'))
->acceptJson()
->timeout(20)
->get('https://vatapi.be/api/v1/vat/'.rawurlencode($vatNumber))
->throw()
->json();
// true = valid, false = invalid, null = no definitive answer right now (retry later)
$valid = $result['valid'];
const vatNumber = 'BE0684579082';
const response = await fetch(`https://vatapi.be/api/v1/vat/${encodeURIComponent(vatNumber)}`, {
headers: { Authorization: `Bearer ${process.env.VAT_API_KEY}`, Accept: 'application/json' },
signal: AbortSignal.timeout(20_000),
});
// On 429, wait the seconds in the Retry-After header.
if (!response.ok) throw new Error(`VAT API error ${response.status}`);
const result = await response.json();
// true = valid, false = invalid, null = no definitive answer right now (retry later)
console.log(result.valid, result.name, result.source, result.checked_at);
import os
from urllib.parse import quote
import requests
vat_number = "BE0684579082"
response = requests.get(
f"https://vatapi.be/api/v1/vat/{quote(vat_number, safe='')}",
headers={"Authorization": f"Bearer {os.environ['VAT_API_KEY']}", "Accept": "application/json"},
timeout=20,
)
response.raise_for_status() # on 429, wait response.headers["Retry-After"] seconds
result = response.json()
# True = valid, False = invalid, None = no definitive answer right now (retry later)
print(result["valid"], result["name"], result["source"], result["checked_at"])
Pricing
Free
No credit card, no password, no trial that runs out. Sign in with your email and you have a key.
Get a free API key- Per minute
- 60
- Per day
- 5,000
- Sources per lookup
- up to 5
- Cost
- €0
Questions
Is a result from a fallback provider as good as VIES?
Fallback providers query VIES themselves and may cache. Every response lists what each source said and which one decided, so you can apply your own policy. Sources that can only confirm validity are never allowed to mark a number invalid.
Why race instead of trying sources one by one?
VIES regularly answers "busy" or times out for a member state. In a sequential chain, every failure costs you its full timeout before the next source is tried. Racing starts them all at once, so a slow or failing source no longer delays your answer.
What does stale mean?
A stored result older than 24 hours. It is returned immediately, flagged stale: true with its check date, and a background job races all sources to refresh it. Add fresh=1 to wait for a live answer instead.
Can I get proof of a check?
Pass your own VAT number as requester and VIES returns a consultation number, the official proof that you verified the number.
Which countries are covered?
All EU member states plus Northern Ireland (XI). The UK is not covered by VIES and returns a clear 422.
What do you store?
Your email, your checks and the latest known result per VAT number. The privacy page has the details and how to delete everything.
More answers, and how this compares to calling VIES yourself: Compare & FAQ.