Howth Technology Factory
← Insights

· VAT operations · 10 min read

Design VIES validation as a state machine

A VAT number check can return valid, invalid or no reliable answer right now. Collapsing those outcomes into one boolean is how a temporary service problem becomes a customer rejection.

VIES validation workflow with valid, invalid and temporarily unavailable outcomes and a distinct operational action for each
Model the operational result, not just the transport response.

The European Commission describes VIES as a search engine that retrieves VAT registration information from national databases. That distinction matters. Your workflow depends on multiple national systems and on the information each country is permitted to return.

A reliable implementation should therefore keep three states: valid, invalid and temporarily unavailable. Each state needs a different next action.

What “valid” establishes

A valid VIES response means the number is registered for cross-border EU trade at the time of the check. It is useful evidence, but it does not decide the complete VAT treatment of a transaction. Place of supply, what is being sold, the parties’ roles and other facts can still change the answer.

Keep the normalized VAT number, response status, timestamp and any reference returned for the request. When the requesting business’s VAT number is supplied, a service may also return a consultation number. Treat that as part of the validation record, not as a substitute for tax advice.

What “invalid” does not necessarily mean

An invalid response can mean the number does not exist, is not activated for intra-EU transactions, or has not completed registration. The right workflow action is usually to pause, show the normalized value that was checked, and ask the customer or supplier to correct it or provide other evidence.

Do not silently strip a country prefix or keep changing the value until something passes. Normalization should be deterministic and visible.

Why “unavailable” must stay separate

National systems are sometimes unavailable. A timeout, retry exhaustion or upstream service error is not evidence that the VAT number is invalid. Record an error state, retry with a bounded delay, and give operations a path to resume the check later.

This separation is especially important in batches. One unavailable national service should not erase valid results for other rows, and it should not turn the whole batch into a misleading pass/fail result.

Put the state transition before the tax decision

A useful workflow separates the technical lookup from the business decision that follows it. The lookup answers a narrow question: what did VIES return for this normalized identifier at this time? The business workflow then decides whether to continue, pause for correction or wait for a dependable answer.

That separation prevents transport details from leaking into customer treatment. A network timeout should not trigger the same customer message as a confirmed invalid response. Equally, a valid response should not silently approve a transaction whose place-of-supply or customer-status facts still need review.

Model the transition explicitly. A new record begins as pending. A completed lookup moves it to valid or invalid. A retryable technical failure moves it to unavailable, with a next-attempt time and the last error retained. Operations can then filter unresolved work without editing the original result.

Design retries around operational risk

Retries are useful only when they are bounded and visible. Repeating a request immediately can add load to a national service that is already struggling, while an unbounded background loop can leave finance teams believing a check is still making progress.

Use a small retry budget with increasing delays and random variation. Preserve the first failure, the number of attempts and the final error category. If the budget is exhausted, return unavailable to the calling workflow instead of guessing. A later scheduled process can retry that individual record without rerunning successful rows.

Not every error is retryable. A malformed country prefix or structurally invalid identifier should be handled before contacting VIES. Authentication, configuration and schema errors should surface to the operator. Only temporary upstream and transport conditions belong in the unavailable path.

Keep an evidence record that can be explained later

The useful record is not simply “VAT valid: yes”. It should show the normalized identifier sent, when the request was made, which result state was produced, and which optional fields were returned. If a requester VAT number was supplied and a consultation number was returned, retain it with that same check.

Do not overwrite an earlier result when a later retry succeeds. Keep the attempts as a short event history so an operator can explain why a transaction was paused and when it became eligible to continue. This is particularly valuable when the customer corrected the identifier between attempts.

Retention should follow the organisation’s evidence and privacy policy. Business names and addresses may be personal or commercially sensitive data. Store only what the workflow needs, restrict access, and apply the same deletion schedule used for the surrounding transaction record.

Make batches reconcile one input to one output

Bulk validation is easiest to operate when every input produces exactly one result row in the same order or with a stable correlation key. Valid rows, invalid rows and unavailable rows can then be processed independently without losing the relationship to the source file.

A mixed batch should not have a single boolean status. Give the batch aggregate counts, but preserve every item result. If three checks are unavailable, a retry job should receive those three correlation keys rather than the entire original list. The successful evidence remains intact and the unresolved work stays visible.

Name and address are conditional fields

Some national databases do not provide a name or address through VIES. In other cases, data-protection rules mean the authority can only confirm whether a supplied name and address are associated with the number. Your schema should allow those fields to be absent without treating the validation as broken.

A compact response contract

{
  "vatNumber": "IE1234567A",
  "status": "valid | invalid | unavailable",
  "businessName": "string | null",
  "address": "string | null",
  "consultationNumber": "string | null",
  "checkedAt": "ISO-8601 timestamp",
  "error": "string | null"
}

The exact field names can differ. What matters is that absence, invalidity and upstream failure remain distinguishable and that every row retains the value and time actually checked.

Five implementation tests worth keeping

  1. A valid number with name and address returned.
  2. A valid number where the national source omits name or address.
  3. An invalid number that stays invalid after deterministic normalization.
  4. A temporary national-service failure that becomes unavailable, never invalid.
  5. A mixed batch that preserves the individual result and timestamp for every input.

Primary sources