# Validate VAT Number
AI coding agents: run curl -s https://vatcheckapi.com/agents.md and follow it: an API key, the first call and the right plan, step by step.
Validates a VAT number from any of the supported countries: its format and checksum first, then its registration. EU and XI numbers are checked in VIES, the European Commission's VAT register service. GB numbers are checked through a commercial VAT data service for Great Britain. Every check asks the register again; answers are not cached.
Request Method: GET
Request URL: https://api.vatcheckapi.com/v2/check?vat_number=[[ vat_number ]]
# Request Parameters
| Parameter | Type | Mandatory | Description |
|---|---|---|---|
apikey | string | ️ | Your API Key |
vat_number | string | ️ | The VAT number to check. Include the two-letter country prefix (e.g. LU26375245), or leave it out and pass country_code |
country_code | string | The country of a vat_number without prefix (e.g. LU). One of the supported country codes. Ignored when the vat_number starts with a supported prefix | |
requester_vat_number | string | Your own EU VAT number, with its country prefix (e.g. ATU63611700). VIES then returns a consultation number. At most 32 characters. No extra cost |
# How input is read
You can send VAT numbers the way people write them:
- Spaces, dots and dashes are removed:
lu 2637-5245andLU26375245are the same number. - Lower case is accepted, in
vat_number,country_codeandrequester_vat_number. - Greece is
ELin VAT numbers.GRis accepted too, as a prefix or ascountry_code. The response always saysEL.
The response shows the number as it was checked: country_code, and vat_number without the prefix, in upper case.
# Sample Request
curl -G https://api.vatcheckapi.com/v2/check \
-d vat_number=LU26375245 \
-d requester_vat_number=ATU63611700 \
-H "apikey: YOUR-APIKEY"
# Sample Response
{
"country_code": "LU",
"vat_number": "26375245",
"format_valid": true,
"checksum_valid": true,
"registration_info": {
"is_registered": true,
"name": "AMAZON EUROPE CORE S.A R.L.",
"address": "38, AVENUE JOHN F. KENNEDY\nL-1855 LUXEMBOURG",
"address_parts": null,
"consultation_number": "WAPIAAAAZ3x9Q1bk",
"checked_at": "2026-10-17T09:30:00.000000Z"
},
"registration_info_history": []
}
Without requester_vat_number, consultation_number is null.
# Response Fields
| Field | Description |
|---|---|
country_code | The country prefix of the number (EL for Greece, XI for Northern Ireland) |
vat_number | The number as it was checked: without prefix, spaces, dots and dashes, in upper case |
format_valid | Whether the number has the country's VAT number format |
checksum_valid | Whether the number's check digits are correct, for countries that have them. If format_valid or checksum_valid is false, no register was asked |
registration_info.is_registered | Whether the register knows the number as a valid VAT number. Always false when the format or checksum is invalid |
registration_info.name | The registered name, or null (not registered, or the register publishes none) |
registration_info.address | The registered address as one string, lines separated by \n, or null |
registration_info.address_parts | Reserved for a split address. Currently always null |
registration_info.consultation_number | The VIES consultation number of this check, or null. See Consultation number |
registration_info.checked_at | When this check asked the register (UTC, ISO 8601 with microseconds, e.g. 2026-10-17T09:30:00.000000Z). null when the format or checksum is invalid |
registration_info_history | Earlier states of this number, newest first. Empty when nothing changed. See below |
# registration_info_history
When the registered name, address or registration status of a number changes between two checks, we keep the earlier state. Each item has:
| Field | Description |
|---|---|
is_registered | The registration status before the change |
name | The name before the change, or null |
address | The address before the change, or null |
checked_at | When that earlier state was first seen (ISO 8601, UTC), or null |
created_at | When the change was recorded, as YYYY-MM-DD HH:MM:SS in UTC |
The history only covers checks made through vatcheckapi. It is always empty for invalid formats and for sandbox keys.
# Consultation Number
A consultation number is VIES's proof that a VAT number was checked at a certain time, by a certain requester. Tax authorities in the EU can ask for it as evidence that you verified your customer's VAT number, for example before you invoice with the reverse charge. Keep it with the invoice.
To get one, send your own VAT number as requester_vat_number:
- It must be an EU VAT number (the 27 member states or
XI) with its country prefix. - We check its format and checksum first. A typo or a non-EU number is answered with a
422before VIES is asked. - If VIES rejects the requester number, the answer is a
422too. Neither422is billed. - The consultation number costs nothing extra. The check costs 1 request as usual.
consultation_number is null without a requester, for invalid formats, and when VIES returns none. It is also null for GB numbers: UK numbers are not checked through VIES, so the API cannot return a consultation number for them yet.
Germany's BZSt also offers a qualified confirmation request (qualifizierte Bestätigungsabfrage), which compares name and address. The API does not offer it.
# Cost
| Answer | Cost |
|---|---|
200: registered or not registered | 1 |
200 with format_valid: false or checksum_valid: false (no register asked) | 1 |
200 with a consultation number | 1 (no extra cost) |
422: invalid parameters, or VIES rejected the number or the requester | 0 |
503: the register is not available | 0 |
401, 403, 429 | 0 |
| Any request with a sandbox key | 0 |
The X-Cost response header states what a call cost.
# Errors
| Status | When | Counted |
|---|---|---|
401 | No API key, or an invalid one. See status codes (opens new window) | No |
403 | The referrer is not on your key's whitelist (referrer_not_allowed), the key belongs to another EverAPI product (key_not_allowed_for_product), or a free account with an unverified email address has used its 5 requests (email_not_verified) | No |
422 | vat_number is missing or not a string | No |
422 | country_code is missing (the number has no prefix) or not one of the supported countries | No |
422 | requester_vat_number is not a string, longer than 32 characters, not an EU VAT number with prefix, or has an invalid format or checksum | No |
422 | VIES rejected the VAT number as invalid input, or rejected the requester number | No |
429 | Your monthly quota is used up, or the free plan's minute limit is reached | No |
503 | VIES, the member state's register or the GB data service is not available, or did not answer in time | No |
A missing vat_number gets the generic validation body:
{
"message": "Validation error",
"errors": {
"vat_number": ["The vat number field is required."]
},
"info": "For more information, see documentation: https://vatcheckapi.com/docs/status-codes#_422"
}
A country_code or requester_vat_number error names the problem in message:
{
"message": "The requester VAT number is not a valid AT VAT number.",
"errors": {
"requester_vat_number": ["The requester VAT number is not a valid AT VAT number."]
}
}
When VIES rejects the input, the body is a bare message: VIES rejected the VAT number as invalid input. or VIES rejected the requester VAT number. Check requester_vat_number.
The 503 body is a bare message as well:
{
"message": "The country's VAT validation service is currently not available. Please check again later."
}
Retry a 503 a little later. The VIES status endpoint (opens new window) shows for free which member states VIES can check right now.
# Timing
VIES is slow at times. A check makes up to 5 attempts of at most 10 seconds each, with short pauses, within one deadline of about 55 seconds. If no attempt gets an answer by then, the API answers 503. Most checks finish within a few seconds. Set your HTTP client's timeout to at least 60 seconds.
When VIES reports a member state (or VIES as a whole) as unavailable, checks for it answer 503 at once, without waiting.
# Sandbox
Requests with a sandbox API key (opens new window) never ask a register and cost nothing (X-Cost: 0):
- Every number with a valid format and checksum comes back as registered to
GOOGLE IRELAND LIMITED,3RD FLOOR, GORDON HOUSE, BARROW STREET, DUBLIN 4. ATU00000006comes back as not registered, withnameandaddressset tonull.- With a
requester_vat_number,consultation_numberisWAPI0000000SANDBOX(nullforGBnumbers). The requester number is checked as with a live key. checked_atis the time of the request.registration_info_historyis always empty.- A number with an invalid format or checksum gets the same answer as with a live key.
# Supported Countries
The API validates VAT numbers from the following 29 countries: the 27 EU member states, the United Kingdom, and Northern Ireland (which uses the XI prefix for goods trade with the EU). Greece uses the VAT code EL; GR is accepted too and answered as EL.
| Code | Country | Code | Country |
|---|---|---|---|
AT | Austria | IT | Italy |
BE | Belgium | LT | Lithuania |
BG | Bulgaria | LU | Luxembourg |
CY | Cyprus | LV | Latvia |
CZ | Czechia | MT | Malta |
DE | Germany | NL | Netherlands |
DK | Denmark | PL | Poland |
EE | Estonia | PT | Portugal |
EL | Greece | RO | Romania |
ES | Spain | SE | Sweden |
FI | Finland | SI | Slovenia |
FR | France | SK | Slovakia |
GB | United Kingdom | XI | Northern Ireland |
HR | Croatia | ||
HU | Hungary | ||
IE | Ireland |
Requests with any other country code fail with a 422 validation error (opens new window).