A customer enters a valid GB VAT number at checkout, your code sends it to VIES, and the response comes back as invalid. The customer assumes your business can't handle UK billing. Your support team sees a registration that looks genuine. The problem is usually routing, not the number.
VAT number verification in the UK changed after Brexit. Great Britain registrations now follow a different verification path from EU registrations, while Northern Ireland numbers under the protocol retain a VIES workflow. For developers, the change affects validation endpoints, error handling, caching, checkout states, and the evidence you retain for B2B invoices.
Table of Contents
- Why UK VAT Verification Breaks After Brexit
- Format Validation Before Remote Lookups
- Choosing Between HMRC and VIES Services
- Handling Edge Cases and Service Failures
- Implementing TaxID API for Production Reliability
- UX Decisions for Checkout and Billing Flows
Why UK VAT Verification Breaks After Brexit
A pre-Brexit billing integration often had a simple rule: take a VAT number, normalize it, and submit it to VIES. That approach fails for ordinary Great Britain registrations because VIES is no longer the correct verification system for numbers with the GB prefix. Since Brexit took effect on 31 December 2020, Great Britain VAT numbers are verified through HMRC's dedicated service, not through the EU's VIES network. HMRC's UK VAT checker can confirm whether a UK VAT registration number is valid and may return the registered business name and address.

The prefix determines the route
The routing rule is jurisdictional, not merely geographic:
- GB identifies an ordinary Great Britain registration and should go to HMRC.
- EU member-state prefixes should go to VIES.
- XI identifies a Northern Ireland VAT number covered by the protocol, and VIES can still be used for its verification.
That means “UK VAT number” isn't specific enough for an API decision. Your system needs to distinguish the prefix before it chooses a remote service. A single endpoint can still be useful at your application boundary, but behind that endpoint you need a routing layer that understands GB, XI, and EU country codes.
This matters in more places than checkout. SaaS platforms use VAT status when generating invoices and applying B2B tax treatment. Marketplaces validate sellers and suppliers. Finance workflows check customer records before accepting tax details. A failure in any of those paths can either reject a legitimate business or allow an invoice to be issued without the verification evidence your process expects.
Production rule: Never treat “UK” as one verification jurisdiction. Treat the prefix as routing data.
Teams that built their validator before 2021 should review it even if it appears to work for most customers. The code may still call VIES for every UK-related number, assume every UK identifier starts with one format, or interpret a remote failure as proof that the customer supplied an invalid registration. For broader context on why a VAT registration can matter to a trading business, see this practical guide to VAT registration benefits explained, then review the implementation implications in this post-Brexit UK VAT API guide.
Format Validation Before Remote Lookups
Remote verification should be the second layer, not the first. Before making an HMRC or VIES request, normalize the input, identify the prefix, and reject values that plainly cannot be VAT numbers. This gives the user immediate feedback and prevents avoidable calls to services that have latency, quotas, maintenance windows, and occasional availability problems.
Normalize without destroying evidence
Keep both the raw value and the canonical value. The raw value is useful for support and audit logs, while the canonical value is what your validator submits.
A practical normalization function can:
- Trim leading and trailing whitespace.
- Convert letters to uppercase.
- Remove spaces and common separators for the lookup value.
- Preserve the original input separately.
- Extract the first two letters as the country or jurisdiction prefix.
For a basic application-side check, the patterns can be expressed like this:
^GB[0-9]{9}$
^GB[0-9]{12}$
^XI[0-9]{9}$
These checks cover the common digit lengths described in UK VAT formatting guidance, but a regex isn't an authority. UK formats include structured ranges and special cases, so a syntactically plausible value can still be inactive or assigned to another entity. The format layer should answer only, “Is this shaped like a value worth submitting?”
The GB patterns should also account for known structured prefixes used by certain entities, including government-related registrations and health service numbers. Don't make the client-side expression so restrictive that it rejects a legitimate special range before HMRC sees it. A good approach is to keep format rules versioned on the server, where you can update them without forcing an immediate client release.
For Northern Ireland, keep the XI prefix intact when routing to VIES. Don't convert it to GB, and don't infer the jurisdiction from a customer's address. The prefix supplied for VAT identification is the relevant routing signal.
Separate syntax from status
Your API response should distinguish at least three outcomes:
- Malformed: the value fails local format checks.
- Invalid or inactive: the authoritative service responds that the number isn't valid.
- Unavailable or pending: the service couldn't provide a reliable answer.
That separation prevents a timeout from becoming a customer-facing “invalid VAT number” message. For a deeper treatment of accepted UK structures, see the UK VAT number format reference.
Client-side validation can show a typo immediately, but the server must repeat the check. Browser validation improves interaction speed, while server-side validation protects billing logic from manipulated requests and inconsistent client implementations.
Choosing Between HMRC and VIES Services
The routing decision should be explicit and testable. Parse the canonical prefix, map it to a service, and record the chosen route with the validation request. That last detail matters when support investigates why a GB value was checked against HMRC while an XI value was sent to VIES.
| Prefix | Jurisdiction | Service | Returns |
|---|---|---|---|
GB |
Great Britain | HMRC UK VAT checker | Validity, and for valid registrations the registered business name and address |
| EU member-state prefix | EU member state | VIES | VAT registration status and available business details |
XI |
Northern Ireland under the protocol | VIES | VAT registration status and available business details |
HMRC for Great Britain
HMRC is the authoritative route for ordinary GB registrations. Its service is designed to confirm whether a UK VAT registration number is valid and can return the registered name and address. Your integration should treat those returned fields as response data, not as user-entered truth. If the name or address differs from the customer's input, flag the mismatch for review rather than rewriting the account automatically.
HMRC's internal guidance describes the UK VAT number checker as the most reliable way to check a UK registration. It also explains that VIES remains relevant for EU registrations and Northern Ireland Protocol trading, which is the basis for the split routing model. HMRC's internal verification guidance is useful when documenting this decision for engineers, finance teams, and auditors.
VIES for EU and XI values
VIES remains the EU-wide mechanism for checking VAT numbers in member states, and it can also verify XI numbers. Its role is therefore narrower for UK-related traffic than it was before Brexit, but it hasn't disappeared from a cross-border billing stack.
Operationally, VIES is commonly consumed through a SOAP interface, while HMRC integrations are generally approached as REST-style service calls. That interface difference affects client libraries, request logging, timeout handling, and test strategy. Avoid scattering service-specific behavior through checkout code. Put it behind a provider interface such as validateGB, validateVies, and a shared result model.
The shared model should carry the prefix, provider, status, returned legal details, checked timestamp, correlation ID, and an error classification. With that structure, changing a provider or adding a fallback doesn't require rewriting invoice or checkout logic.
Handling Edge Cases and Service Failures
A real registration can fail an immediate lookup. HMRC warns that newly issued registrations may take up to 48 hours to appear in its databases, so a new supplier or customer can temporarily return no match. Treat that response as uncertainty, not automatic evidence of fraud. The product should distinguish a missing record from a confirmed invalid number, following the previously cited HMRC guidance.

Don't block a legitimate onboarding
Checkout needs a bounded response. Reject malformed input immediately with an inline error. If the selected authoritative service returns a confirmed invalid result, ask for correction or send the account to review. A timeout, provider outage, or potentially new registration should create a pending verification state rather than turning an unavailable dependency into a customer rejection.
A background worker can retry pending records with exponential backoff and jitter. Persist the attempt count, next-attempt time, provider response class, and reason for the pending state. Make the worker idempotent, so replaying a job cannot create duplicate customers, invoices, or audit events.
For a new GB registration, schedule a delayed recheck instead of polling rapidly. Communicate the HMRC registration delay to the user, then let the worker retry after an appropriate interval. The same approach applies to VIES outages. This resilience guide for VIES downtime describes queueing and retry patterns for slow or unavailable remote services.
Classify failures precisely
Use distinct states:
- Invalid: the provider answered and confirmed that the number is invalid.
- Pending: the number may be newly issued or awaits its scheduled recheck.
- Unavailable: the provider timed out or returned a service failure.
- Verified: the provider confirmed the number and returned its details.
- Manual review: an operator approved an exception and recorded the reason.
VIES outages require their own path. Do not retry every request immediately, and do not send a VIES number to HMRC just because VIES is unavailable. The authorities cover different registration scopes, so that fallback can produce a misleading result. Queue the request, show the customer a neutral status, and alert operators when failures exceed the team's internal threshold.
Keep the same audit discipline when tax validation shares an onboarding flow with identity or transaction monitoring. The guide to AML KYC compliance for web3 offers relevant context for review queues and evidence trails. Record the original value, provider, response, retry history, and final decision so finance and support can explain what happened.
Implementing TaxID API for Production Reliability
A team can build separate HMRC and VIES adapters, normalize their different response formats, maintain retries, and operate provider-specific monitoring. That gives maximum control, but it also creates another internal subsystem to own. A unified provider such as TaxID exposes one REST endpoint and handles country-specific format checks, provider routing, caching, and normalized error responses.

TaxID's documented product behavior includes format checks before remote calls, Redis-backed 24-hour caching, and machine-readable errors such as vat_invalid and service_unavailable. Cached lookups can return in sub-10ms, according to the publisher's product information, which is useful when the same customer enters a billing flow repeatedly. The service offers a free tier of 100 monthly validations, with paid plans for higher usage.
Node.js integration pattern
Keep the provider call on your server. The browser should submit the VAT number to your backend, which then calls the validation API and decides whether tax treatment can change.
async function validateVat(vatNumber) {
const response = await fetch("https://api.taxid.dev/v1/validate", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${process.env.TAXID_API_KEY}`
},
body: JSON.stringify({ tax_id: vatNumber })
});
const body = await response.json();
if (response.ok) {
return {
status: "verified",
companyName: body.company_name,
address: body.address
};
}
if (body.code === "vat_invalid") {
return { status: "invalid" };
}
if (body.code === "service_unavailable") {
return { status: "pending" };
}
throw new Error(`VAT validation failed: ${body.code || "unknown_error"}`);
}
The exact request and response fields should follow the current API documentation. The important implementation choice is the state mapping. A provider outage must not be handled as an invalid customer number.
Python and cache-aware server logic
import os
import requests
def validate_vat(tax_id):
response = requests.post(
"https://api.taxid.dev/v1/validate",
headers={
"Authorization": f"Bearer {os.environ['TAXID_API_KEY']}",
"Content-Type": "application/json",
},
json={"tax_id": tax_id},
timeout=5,
)
payload = response.json()
if response.ok:
return {
"status": "verified",
"company_name": payload.get("company_name"),
"address": payload.get("address"),
}
code = payload.get("code")
if code == "vat_invalid":
return {"status": "invalid"}
if code == "service_unavailable":
return {"status": "pending"}
response.raise_for_status()
Cache by the normalized tax ID and country prefix, not by the raw string. Store the provider result and checked time with the cached value, and invalidate it when an administrator requests a fresh verification. For low-volume projects, the free allowance may cover early testing. Higher-volume checkouts should model cache hit behavior, new-customer traffic, and background rechecks before selecting a paid plan.
UX Decisions for Checkout and Billing Flows
VAT validation affects a user's ability to buy, but the remote service doesn't know your product's tolerance for uncertainty. Treat the result as a business state, then choose an interface response that matches the risk.
A malformed number deserves an immediate inline correction. A clear invalid response can block submission when the VAT number is required for the selected B2B treatment. A timeout or pending registration deserves a warning and an asynchronous path, not a red error that accuses a legitimate customer of supplying false data.

Separate customer feedback from tax decisions
Use plain language in the interface:
- Format error: “Enter a valid UK or EU VAT number.”
- Confirmed invalid: “We couldn't verify this VAT number. Check the prefix and digits.”
- Pending: “We're checking this registration. You can continue, and we'll update the billing record.”
- Manual review: “We need to review your business details before finalizing tax treatment.”
Don't expose SOAP faults, provider names, or raw timeout messages at checkout. Keep those details in structured logs and an operator view. Customers need a useful next action, while engineers need the diagnostic context.
For repeat customers, a cached verification can keep billing fast, provided your tax policy accepts the cache lifetime and your record shows when the value was last checked. For a new signup, real-time verification is sensible when the provider is available, but the account should still have a pending state when the provider can't answer.
Manual override is sometimes necessary for an active commercial relationship, especially when a newly issued registration hasn't appeared yet. Make it an administrative action, require a reason, record the operator identity, preserve the original provider response, and schedule a recheck. Never let a hidden database flag bypass validation.
In invoicing, don't apply reverse-charge or other B2B treatment solely because a field contains a VAT-looking string. Tie the tax decision to a verified or explicitly approved state, retain the returned company details, and show the VAT number on the generated invoice according to your accounting workflow.
TaxID provides a single REST integration for VAT and company identification validation, including UK routing, normalized company details, caching, and machine-readable failure states. If you're implementing vat number verification uk for SaaS billing, B2B checkout, or supplier workflows, visit TaxID to review the API and start with the available free validation tier.