The VIES API: REST vs SOAP, the error codes and the limits
The VIES API is free and needs no key: POST countryCode and vatNumber as JSON to https://ec.europa.eu/taxation_customs/vies/rest-api/check-vat-number and read valid, plus the trader’s name and address where the member state publishes them; add your own VAT number as the requester to receive a consultation number. The older SOAP service (checkVatService) answers the same question (European Commission, VIES technical information). What VIES does not give you is a cache for the hours a member state is down, a retry policy, or the same answer shape for every country: that is the part you build, or delegate.
·
- No key, no sign-up, no fee: the service is operated by the European Commission (DG TAXUD) for checking EU VAT numbers; it publishes no fixed rate limit but refuses requests with
MS_MAX_CONCURRENT_REQorGLOBAL_MAX_CONCURRENT_REQwhen too many are in flight. - One request checks one number. VIES forwards it to the register of the member state named by the prefix (
ELfor Greece,XIfor Northern Ireland, goods only). - Name and address are returned only where the member state publishes them; Germany, for one, answers
---for both. - A consultation number (
requestIdentifier) is issued only when you identify yourself with your own EU VAT number; it is the evidence of the check that a tax audit accepts.
What does a REST call look like?
One POST with a JSON body. The answer is JSON; a failure is either an HTTP error or a userError field other than VALID / INVALID.
curl -X POST "https://ec.europa.eu/taxation_customs/vies/rest-api/check-vat-number" \
-H "Content-Type: application/json" \
-d '{"countryCode":"DE","vatNumber":"136695976"}'curl -X POST "https://ec.europa.eu/taxation_customs/vies/rest-api/check-vat-number" \
-H "Content-Type: application/json" \
-d '{"countryCode":"DE","vatNumber":"136695976",
"requesterMemberStateCode":"FR","requesterNumber":"40303265045"}'Which fields come back?
valid— true when the number is registered for intra-EU transactions in that member state on the request date.requestDate— the date of the check, the one to store with the answer.name,address— the registered trader, or---where the member state does not publish them.requestIdentifier— the consultation number, only when a requester was given.userError—VALID,INVALID, or the reason the check could not be made (next section).
What do the VIES error codes mean?
| Code | Meaning | What to do |
|---|---|---|
MS_UNAVAILABLE | The member state’s register did not answer | Serve your last dated answer or retry later; never read it as "invalid" |
SERVICE_UNAVAILABLE, TIMEOUT | The Commission’s relay failed or was too slow | Retry with backoff, bounded |
MS_MAX_CONCURRENT_REQ, GLOBAL_MAX_CONCURRENT_REQ | Too many requests in flight, for one state or overall | Slow down; pace your batch |
INVALID_INPUT | The country code or the number is malformed | Fix the input; check the structure before calling |
INVALID_REQUESTER_INFO | The requester VAT number is malformed | Check your own number and its prefix |
IP_BLOCKED, VAT_BLOCKED | The caller or the number is blocked by the service | Stop and investigate the request pattern |
REST or SOAP: which one should you call?
Both are the same service in front of the same 27 registers and answer the same question; they differ in transport, in how the consultation number is asked for, and in what fails first. The REST API (JSON, published in 2021) is the one to build on; the SOAP service (the original checkVatService, WSDL at https://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl) is the fallback worth keeping, because the two front ends do not always fail together.
| REST API | SOAP service | |
|---|---|---|
| Endpoint | POST …/vies/rest-api/check-vat-number, JSON in and out | POST …/vies/services/checkVatService, SOAP 1.1 envelope, SOAPAction empty |
| Simple check | countryCode + vatNumber | operation checkVat |
| Consultation number | requesterMemberStateCode + requesterNumber in the same body; requestIdentifier in the answer | operation checkVatApprox with requesterCountryCode + requesterVatNumber; requestIdentifier in the answer |
| Errors | userError field (MS_UNAVAILABLE, TIMEOUT…) in a 200, or an HTTP 4xx/5xx | a SOAP fault whose faultstring is the same code |
| Status of the member states | GET …/rest-api/check-status (relay and each national component) | none |
| Typical failure mode | HTTP 5xx or a gateway timeout under load | the same codes as faults; occasionally answers when REST does not |
| Tooling | any HTTP client | any HTTP client with a hand-written envelope, or a SOAP library |
Veriport calls REST first and retries once over SOAP when REST fails for a reason that is not the number’s; input and requester errors are final on the first transport.
What are the limits of the VIES API?
The Commission publishes no numeric quota. What it does publish and enforce: a cap on concurrent requests per member state (MS_MAX_CONCURRENT_REQ) and overall (GLOBAL_MAX_CONCURRENT_REQ), blocking of an address or a number whose request pattern looks abusive (IP_BLOCKED, VAT_BLOCKED), and the scheduled unavailability windows of each national component (the help page lists them; the self-monitoring page shows the live state). In practice: send one request at a time per member state from one address, wait for the answer before the next, retry the concurrency codes after a pause rather than immediately, and never validate the same number in a loop. A batch of 10,000 numbers takes hours this way; that is the service’s design, not a defect.
- No key, no quota, no SLA: VIES is a public utility, not an API product; a 99.9 % expectation is the wrong one.
- Timeouts are yours to set: Veriport waits 8 seconds per transport; the Commission’s help page mentions no figure.
- Name and address are published by some member states only; Germany answers
---; that is not a limit you can work around through VIES. - The UK (GB) left VIES on 1 January 2021; only XI numbers remain. Switzerland and Norway were never in it.
What do you still have to build around it?
Four things, in the order an outage makes you need them: a structural check (prefix, length, check digit) so impossible numbers never reach VIES; a cache of the last answer per number, dated and marked as cached when you serve it during an outage; a bounded retry with backoff that honours the concurrency codes; and storage of the evidence (date, result, consultation number). The guide "VIES is down: validate anyway" walks through each. Veriport is that layer as one REST call, with the same answer shape for the 27 member states and Northern Ireland, 100 calls a month free.
Questions
- Is the VIES API free?
- Yes. The European Commission provides VIES at no charge and without registration, through a REST API and a SOAP service.
- Does VIES return the company name?
- Only where the member state publishes it. Several do not: Germany, for example, returns "---" for the name and the address, and confirms them only through its own qualified confirmation service.
- Can I check UK VAT numbers on VIES?
- Not since 2021, except Northern Ireland numbers with the
XIprefix, for trade in goods. Great Britain numbers are checked with HMRC’s own API.
100 calls a month, the cache and the retries included.
Get a free keySources
- VIES REST API — check-vat-number, check-status (technical information) — European Commission, DG TAXUD, consulted 2026-10-24
- VIES SOAP service — checkVatService WSDL — European Commission, DG TAXUD, consulted 2026-10-24
- VIES — help page: what the consultation number proves, member-state availability — European Commission, DG TAXUD, consulted 2026-10-24
- VIES — VAT Information Exchange System: FAQ and VAT number structures (Q11) — European Commission, DG TAXUD, consulted 2026-10-24
- VIES — Self-monitoring: availability of each national component (MSA / XI availability), the data behind the check-status endpoint — European Commission, DG TAXUD, consulted 2026-10-28. The Commission runs the central relay; each member state runs and maintains its own national component, which is why one state can be unavailable while the others answer.