What MS_UNAVAILABLE, MS_MAX_CONCURRENT_REQ and the rest actually mean — and why none of them mean the VAT number is invalid.
isValid: false for every failure mode. A deregistered VAT number, a country whose database is offline, a timeout, a rate-block — all of them come back as isValid: false. The only thing that tells them apart is the userError field, and most client libraries throw it away. That single design detail is why "VIES said my customer's valid VAT number is invalid" is such a common complaint.
| Code | What it means | Correct handling |
|---|---|---|
| VALID | The number is registered for intra-EU trade right now. | Store the result and the consultation number. |
| INVALID | Genuinely not registered. real answer | The only code that justifies rejecting the number. |
| MS_UNAVAILABLE | That member state's database is down or unreachable. outage | Retry with backoff. Never treat as invalid. |
| MS_MAX_CONCURRENT_REQ | The member state is rate-limiting your concurrent requests. outage | Lower parallelism, retry with backoff. |
| GLOBAL_MAX_CONCURRENT_REQ | VIES as a whole is rate-limiting. outage | Back off and serialise your batch. |
| SERVICE_UNAVAILABLE | The VIES service itself is unavailable. outage | Retry; check the live status page. |
| TIMEOUT | The member state did not answer in time. outage | Retry — commonly clears in minutes. |
| SERVER_BUSY | Temporary overload. outage | Retry with backoff. |
| INVALID_INPUT | Malformed number, or a country prefix VIES doesn't know. your request | Fix the format. Note Greece is EL, not GR. |
| INVALID_REQUESTER_INFO | The requester VAT number you supplied was rejected. your request | Use your own real, currently valid VAT number — otherwise no consultation number is issued. |
| VAT_BLOCKED / IP_BLOCKED | VIES has blocked the number or your IP, usually after abuse-level traffic. blocked | Stop, reduce volume, contact the Commission if persistent. |
Of the eleven codes above, exactly one — INVALID — is a statement about the VAT number. The rest are statements about the service. If your integration collapses them all into a boolean, then every time a member state has a bad afternoon your system quietly starts rejecting real customers, blocking checkouts, or charging VAT on invoices that should have been zero-rated. Nobody notices until a customer complains, and by then the invoices are out.
We read userError and map it honestly. The outage codes never produce a valid: false:
{ "error": "vies_unavailable", "retryable": true }
Before returning that, we try to answer anyway. For France, Poland, Finland, Czechia and Denmark — the member states that publish a free official register — we re-check the number against that register live and flag where the answer came from:
{ "valid": true, "name": "ORLEN S.A.", "source": "national_vat_register_pl", "consultationNumber": null }
Everywhere else, if your own key validated that exact number within the last 24 hours, you get that confirmed result back flagged source: "cache" with the original timestamp — so your checkout keeps moving — and you retry for a fresh consultation number when the country recovers. A rejected requester returns invalid_requester rather than silently degrading. Full per-country detail is in the coverage table.
One endpoint: validity, company name and address, the official VIES consultation number for your audit file, and error handling that tells the truth about outages. Free tier is 100 validations a month, no card.
Get your free API key Read the docs →