All articles →

Validating VAT numbers for business customers: when you may refuse the order and when you must not

When you sell to business customers in the EU you are required to check that the VAT number they provide is valid. The VAT Check API does three things for you: it validates the number against VIES (with a 24-hour cache), it checks compliance with the Omnibus-richtlijn 2019/2161 (the mandatory “lowest-price-of-30-days” rule for any discount), and it calculates the correct shipping-threshold for the 27 EU VAT rates. Knowing what the API actually tells you is the key to deciding whether you may refuse an order or whether you must proceed with it.

---

### What the VIES response really tells you

The VAT Check API always returns an HTTP 200 status, even when the VIES service itself is experiencing an outage. The real signal is in the **userError** field:

* **VALID** or **INVALID**. these are the only two values that constitute a judgment about the number.
* **MS_UNAVAILABLE, MS_MAX_CONCURRENT_REQ, GLOBAL_MAX_CONCURRENT_REQ, SERVICE_UNAVAILABLE, TIMEOUT**. these values mean *“we could not reach the VIES service right now”*. They are **not** a judgment about the number’s validity.

If you act on the HTTP 200 code alone and ignore the userError field, you will cache a temporary service problem as a permanent “INVALID” result. That can lead you to refuse an order that is actually perfectly valid.

---

### When you may refuse the order

You may refuse an order **only** when the API returns a definitive judgment that the VAT number is invalid **and** the userError field shows that the judgment is reliable.

* **INVALID** with userError = null (or any value that does **not** indicate a service problem) → the number is definitely not a valid EU VAT number.
In this case you are allowed to refuse the order because the customer has supplied an identifier that cannot be used for intra-EU VAT exemption.

* **VALID** with userError = null (or a non-service-error value) → the number is confirmed as valid. You must **not** refuse the order on VAT grounds; the customer is entitled to the VAT-exempt treatment you are offering.

Any other userError value (MS_UNAVAILABLE, MS_MAX_CONCURRENT_REQ, GLOBAL_MAX_CONCURRENT_REQ, SERVICE_UNAVAILABLE, TIMEOUT) tells you only that the VIES service could not be reached at that moment. Treating that as “invalid” would be a mistake, because the number might actually be valid. In those situations you must **not** refuse the order outright; instead you should treat the result as unknown and either retry the request after a short delay or proceed with the order while flagging it for manual review.

---

### When you must **not** refuse the order

There are three situations where refusing an order based solely on the VAT check would be non-compliant:

1. **Service-error responses**. As noted, any userError that signals a VIES outage means you have no reliable information about the number’s validity. Refusing the order would be based on a false assumption. The correct approach is to retry the request (respecting the 24-hour cache) or to process the order with a note that the VAT status could not be confirmed at that moment.

2. **Omnibus-richtlijn compliance**. The API also checks whether a discount you are offering respects the mandatory “lowest-price-of-30-days” rule. This is a compliance check, not a validity test of the VAT number. If the API flags a violation, you must **adjust the price** to meet the rule; you cannot simply refuse the sale because the discount is too steep. The API’s judgment here is about price compliance, not about the VAT number itself.

3. **Shipping-threshold calculation**. The API calculates the correct shipping-threshold for the destination’s VAT rate across the 27 EU rates. If the calculated threshold is higher than the order value, you must apply the appropriate VAT or shipping rules; you cannot refuse the order because the threshold looks “too high”. The API’s output is a factual calculation, not a validity judgment.

In each of these cases the API is giving you a **deterministic fact** (price rule, shipping threshold) or an **uncertainty** (service error). Refusing the order would be disproportionate and could violate consumer-protection rules.

---

### Practical workflow

1. **Call the VAT Check API** with the supplied number and the country code.
2. **Inspect the userError field**:
* If it is null (or any value that does **not** indicate a service problem) and the result is **INVALID**, you may refuse the order.
* If the result is **VALID** (and userError is not a service error) you must proceed with VAT-exempt treatment.
* If the userError signals a VIES outage, retry after a brief pause (respecting the 24-hour cache) or flag the order for manual review; do **not** refuse automatically.
3. **Check the Omnibus flag**. if the API indicates a discount that breaches the lowest-price-of-30-days rule, adjust the price to comply; do not cancel the sale.
4. **Apply the shipping-threshold value** returned by the API; if the order falls below the threshold

The 12 point EU dropship checklist
Check this before you spend a euro on inventory. Free, on your screen straight away.
Get the checklist →