A customer reaches your B2B checkout, enters a VAT number, and expects the total to update immediately. Your application has to decide whether the value is merely well-formed, whether it belongs to a registered business, and whether the transaction can use a tax treatment that depends on that registration. A malformed input should fail quickly. A temporary registry outage shouldn't turn a legitimate customer away. A valid-looking number shouldn't automatically become permission to remove VAT.
That's the practical problem behind a VAT code check. It isn't one request to one magic endpoint. It's a small validation system with local parsing, country-specific rules, authoritative registry queries, error handling, and an audit trail.
Table of Contents
- What a VAT Code Check Actually Does
- How VAT Codes Are Structured
- Country Formats You Will See Most Often
- Validating Format Before Any Remote Call
- When You Need an Authoritative Lookup
- The Reality of Calling VIES in Production
- Putting Format Checks and Lookups Together
What a VAT Code Check Actually Does
Suppose the customer enters DE123456789. Your checkout shouldn't immediately trust it, and it shouldn't send every keystroke to a remote service either. The first job is to clean the value and check whether it resembles a German VAT identifier. The second is to ask an authoritative register whether that identifier is currently valid.
A useful implementation separates three decisions:
- Syntax validation catches input problems such as blank values, misplaced spaces, unsupported characters, or a missing country prefix.
- Format validation applies the selected country's structure, including length, character class, and checksum rules where applicable.
- Registry validation checks whether the identifier exists in the relevant VAT register and, where returned, whether the registered business details match the submitted information.
These checks fail differently. Syntax and format checks run locally and can return a field-level error almost immediately. A registry lookup depends on a network service and a national database, so it can time out, return an error, or produce an answer that contains validity but limited business information.
Practical rule: Treat “well-formed” and “registered” as separate states in your data model.
The European Commission describes VIES as a search engine that queries national VAT registers in real time. The result is valid or invalid, while the underlying data comes from national databases outside the Commission's control. That architecture is why a VAT code check should be layered rather than reduced to a single remote call. The European Commission's VIES guidance explains the registry relationship and the limits of the returned result.
At checkout, those states support different product decisions. A syntactically invalid value can be rejected with “Check the country code and number.” A valid-looking value with an unavailable registry should produce “We couldn't verify this right now,” not “Your VAT number is invalid.” Only an authoritative positive result should support a workflow that depends on current registration.
How VAT Codes Are Structured
Start with the identifier as a routing key. In the common EU representation, it has a country prefix followed by a national VAT identifier. The prefix tells your validator which country rules to apply and which national register sits behind the lookup.
That prefix matters because there isn't one universal EU VAT database with one universal identifier pattern. Each member state maintains its own VAT register, and VIES connects queries to those national systems. The European Commission's audit describes VIES as a common computer network for largely automated exchange between tax administrations, while the national systems continue to supply the underlying information. The EU Court of Auditors report on VIES provides the historical context for that architecture.
A developer should therefore read a VAT code from left to right:
- Country prefix: identifies the jurisdiction and selects the parser.
- National body: contains digits, letters, or both according to local rules.
- Validation features: may include a checksum, control character, or special national convention.
The country prefix isn't always identical to the familiar ISO country code. Greece is the classic trap: its VAT prefix is EL, even though the ISO country code is GR. If your country selector emits GR, a legitimate Greek identifier can fail before the registry ever sees it.
The legal concept of a VAT Identification Number comes from the EU VAT framework, including Council Directive 2006/112/EC. In application code, though, the important point is operational: the format is country-specific. A single global regular expression will either reject legitimate values or accept strings that can never be valid.
For broader context on how tax identifiers differ from other business identifiers, the startup business id guide is a useful reference. For implementation work, keep a country-aware format reference close to your codebase, such as this VAT number format glossary.
Country Formats You Will See Most Often
Real traffic quickly exposes why a universal regex is unsafe. The following examples are structural patterns, not proof that a particular sample is registered.
| Jurisdiction | Common structure |
|---|---|
| Germany | DE followed by 9 digits |
| France | FR followed by 2 alphanumeric check characters and 9 digits |
| Netherlands | NL followed by 9 digits, B, and 2 digits |
| Italy | IT followed by 11 digits |
| Spain | ES followed by a letter or digit, 7 digits, and a final letter or digit |
| United Kingdom | Pre-Brexit GB format commonly used 9 digits, with additional trader schemes |
| Ireland | IE followed by a country-specific pattern, including forms with 7 digits and a letter or 8 digits |
The Netherlands illustrates a common source of bugs. A parser that expects digits only will reject the B in the identifier. France presents a different issue because its two leading characters can be alphanumeric rather than ordinary digits. Spain's mixed structure also means that character position matters, not just total length.
The United Kingdom needs separate treatment in a cross-border system. A pre-Brexit GB identifier isn't interchangeable with an EU member-state identifier, and a team handling Northern Ireland trade may also encounter the XI prefix in the relevant context. Don't apply an EU-only rule to every UK value. Select the validation path from the country and transaction context you support.
Ireland can be awkward for systems that assume one fixed body length. Some patterns use 7 digits and a letter, while business identifiers can use 8 digits. Your parser should use a maintained country ruleset rather than a hand-written assumption embedded in a checkout component.
Greece is the memorable prefix exception. Store the accepted prefix explicitly as EL, and make sure the country selector and normalization layer agree. A user-facing country name such as Greece doesn't tell you which code the VAT registry expects.
A country prefix chooses the parser. It doesn't prove the business exists.
Some jurisdictions also have variants for branches, public bodies, or other trader categories. Your system should preserve the normalized value and the original input, then let the authoritative lookup decide whether the identifier is registered. Format rules are a gate, not a tax conclusion.
Validating Format Before Any Remote Call
A local format check is the cheapest part of the pipeline, so run it before spending network time on VIES. The validator should normalize harmless presentation differences, reject impossible values, and return a result your UI can explain.
A practical normalization sequence looks like this:
- Trim leading and trailing whitespace.
- Convert letters to uppercase.
- Remove spaces and punctuation your input policy allows.
- Read and validate the country prefix.
- Apply the parser for that country.
- Run a checksum rule when the country defines one.
The country rules should live in data or small, testable functions rather than one enormous expression. The VAT number validator guide is a useful companion when deciding how to separate normalization, syntax checks, and registry validation.
Here's a deliberately short pseudocode shape:
function validateVAT(input):
raw = input
value = normalize(input)
if value is empty:
return { ok: false, normalized: null, country: null,
error: "VAT number is required" }
country = extractPrefix(value)
if country is not in supportedCountries:
return { ok: false, normalized: value, country: country,
error: "Unsupported or missing country code" }
body = removePrefix(value, country)
if not countryRules[country].matches(body):
return { ok: false, normalized: value, country: country,
error: "VAT number has the wrong format" }
if countryRules[country].checksum exists
and not countryRules[country].checksum(body):
return { ok: false, normalized: value, country: country,
error: "VAT checksum failed" }
return { ok: true, normalized: value, country: country,
error: null }
The returned object makes the boundary clear. ok: true means the string passed local rules. It does not mean the number is registered, active, or eligible for a particular tax treatment.
Use specific messages instead of exposing a generic “invalid VAT” error. “VAT must start with a supported country code” helps a customer correct an omitted prefix. “French VAT numbers use two check characters followed by nine digits” tells an operations teammate what failed without pretending the registry has been consulted.
Run this gate in the browser for fast feedback, then repeat it on the server. Client-side validation improves the experience, but it's untrusted input and can be bypassed. The server should normalize again before it stores the value or sends it to a remote service.
When You Need an Authoritative Lookup
A format check answers one narrow question: does this string look possible? It can't answer whether a tax authority currently recognizes the number. If your invoice, checkout, or payout depends on registration status, you need an authoritative lookup.
For EU identifiers, VIES is the standard cross-border route. The Commission's service queries national VAT databases in real time, and the response can include validity plus business details where the relevant member state makes them available. The data model should allow for a valid response without a returned name or address.
Outside that route, teams may use national services such as HMRC VAT interfaces for UK records, or commercial providers that aggregate registry sources. The choice depends on the countries you support, the evidence your finance process requires, and how much reliability work you want to own.
Three workflows usually justify the remote check:
- B2B checkout: The customer enters a VAT number and your system is considering a cross-border treatment such as reverse charge. A format pass alone isn't enough evidence that the customer's registration is live.
- Self-billing: Your platform creates an invoice on the supplier's or customer's behalf. A stale or mistyped identifier can contaminate the invoice record and create reconciliation work.
- Marketplace payouts: The marketplace pays a seller in another jurisdiction and needs an identity and registration signal before applying its billing rules.
The trade-off is asymmetric. A false positive can lead you to apply a tax treatment without sufficient support. A remote call, meanwhile, adds latency and can fail even when the customer entered a legitimate number. Your product should represent both outcomes instead of collapsing every non-positive response into “invalid.”

A sensible decision policy might be:
| Result | Meaning | Checkout action |
|---|---|---|
| Format fails | The input can't match the country rules | Ask the customer to correct it |
| Format passes, lookup valid | The register accepted the identifier | Continue according to your tax policy |
| Format passes, lookup invalid | The register didn't confirm it | Don't claim registration-based treatment |
| Lookup unavailable | You have no current answer | Use a defined review or fallback flow |
Tax logic still belongs with your tax team and legal policy. The engineering responsibility is to make the evidence and uncertainty explicit.
The Reality of Calling VIES in Production
VIES is an operational dependency, not a private service with guarantees specific to your application. The Commission says it returns data from national databases outside its control, and the service status is actively monitored. That means a result can depend on the availability of both the shared service and the relevant national register. The official VIES service page should be part of your incident runbook.
Your integration needs more than a request and a boolean. Set a firm timeout so a checkout thread doesn't wait indefinitely. Retry transient failures with backoff and jitter, but don't turn a registry incident into a burst of repeated calls. Cache successful results for a policy-defined period, and be more conservative with negative results because a temporary national outage shouldn't become a durable “invalid” record.
A useful response model separates these states:
validinvalidunavailabletimeoutunsupportedmalformed
That distinction makes customer messaging and finance review much safer. It also prevents observability dashboards from reporting service failures as customer data failures.

Caching also creates governance work. A successful lookup stores a record that your system queried a tax identifier, and it may store returned business details. Define who can access that record, how long you retain it, why you retain it, and how your privacy notice describes the processing. Don't treat Redis or an application database as invisible just because the lookup began as a technical request.
An experienced first-month checklist includes:
- Timeouts: Prevent remote dependency calls from blocking checkout indefinitely.
- Retries: Retry only transient failures, with backoff and jitter.
- Caching: Set separate policies for positive, negative, and unavailable responses.
- Fallbacks: Offer manual evidence collection or a review queue when verification is unavailable.
- Monitoring: Track response states by country and distinguish registry errors from malformed input.
- Audit records: Store the normalized number, requester context, result, and lookup time according to your retention policy.
For a practical explanation of the integration boundary, see this VIES validation implementation guide.
Putting Format Checks and Lookups Together
The pattern has two gates, placed at different trust boundaries.
Gate one runs in the browser. As the customer types or leaves the VAT field, normalize the display value and apply the country-specific format rule. Don't call VIES on every keystroke. The browser should catch obvious mistakes, keep the form responsive, and show a useful correction before submission.
Gate two runs on the server. Receive the submitted value as untrusted input, normalize it again, run the same country parser, and only then decide whether a registry lookup is necessary. The server owns the final decision because a client-side result can be altered or skipped.

A typical request lifecycle looks like this:
- The customer selects a country and enters an identifier.
- The browser normalizes the value and runs the local rule.
- The form displays a precise error or allows submission.
- The server repeats normalization and format validation.
- If the business decision requires current registration, the server checks its cache.
- On a cache miss, the server calls VIES or another appropriate authority.
- The application records the result state and applies the tax workflow only when policy allows it.
The cache key should use the normalized country and VAT body, not the raw string. That prevents separate entries for values that differ only by spaces or letter casing. Store the raw input separately only if you have a clear audit reason and an appropriate retention policy.
Client-side and server-side checks aren't competing approaches. The browser optimizes feedback, the server protects integrity, and the registry lookup supplies evidence that local rules can't provide. A team that keeps those responsibilities separate can change its UI without weakening validation, and can replace or wrap its registry provider without rewriting every checkout component.
Here's a short video walkthrough to help connect the flow to an implementation mindset:
If you're building this into SaaS billing, a marketplace, or a custom checkout, TaxID provides a REST interface for VAT and company identification validation, including normalized status and returned company details where available. Visit TaxID to review the API and decide whether using a maintained validation layer fits your reliability and audit requirements.