Every EU VAT decision in your SaaS or digital product flows from one question: is this customer a business with a valid EU VAT number, or not? Get the answer right and you apply the correct tax treatment automatically. Get it wrong and you either overcharge legitimate B2B customers — losing the sale — or apply zero-rate reverse charge to someone who doesn't qualify, making yourself liable for the full VAT amount. This guide explains how to detect the distinction, validate it legally, and implement the correct treatment in code.
What makes a customer B2B vs B2C under EU VAT law
Under EU VAT Directive 2006/112/EC, the B2B classification for cross-border digital services requires three things: both parties must be VAT-registered, they must be in different EU member states, and the buyer's VAT number must be valid in VIES at the time of supply. Meeting all three conditions entitles you to apply the reverse charge mechanism — the buyer accounts for VAT in their own country, and you invoice at 0%. If any condition fails, you are in B2C territory and must apply the VAT rate of the customer's country.
| Classification | Required conditions | VAT treatment |
|---|---|---|
| B2B cross-border | Both VAT-registered, different member states, valid VIES result | Reverse charge — 0% on your invoice |
| B2B same country | Both VAT-registered, same member state | Standard domestic rate — no reverse charge |
| B2C EU (consumer) | No valid EU VAT number | Customer's country rate via OSS |
| B2C non-EU | Customer outside the EU | Generally outside EU VAT scope |
Warning
You cannot rely on a customer's self-declaration that they are a business. Under Article 17 of EU Regulation 282/2011, the seller must take reasonable steps to verify the buyer's taxable status. VIES validation is that verification step — without it, the zero-rate treatment is legally unsupported.
Detecting B2B status at checkout
The detection logic at checkout has two inputs: the country the customer selects, and whether they provide a VAT number that passes VIES validation. You cannot shortcut this with format-only validation — a syntactically correct VAT number that is not registered in VIES does not entitle the customer to reverse charge treatment.
type VatTreatment =
| 'b2b_reverse_charge'
| 'b2b_domestic'
| 'b2c_eu'
| 'b2c_non_eu';
const EU_COUNTRIES = new Set([
'AT','BE','BG','HR','CY','CZ','DK','EE','FI','FR','DE','GR',
'HU','IE','IT','LV','LT','LU','MT','NL','PL','PT','RO','SK',
'SI','ES','SE'
]);
export async function classifyCustomer(
sellerCountry: string,
customerCountry: string,
vatNumber?: string
): Promise<VatTreatment> {
if (!EU_COUNTRIES.has(customerCountry)) return 'b2c_non_eu';
if (!vatNumber) return 'b2c_eu';
const res = await fetch(
`https://www.taxid.dev/api/v1/validate/${customerCountry}/${vatNumber}`,
{ headers: { Authorization: `Bearer ${process.env.TAXID_API_KEY}` } }
);
const { status } = await res.json();
if (status === 'service_unavailable') {
// VIES is down — allow through, flag for re-validation
return 'b2b_reverse_charge'; // conservative: trust the number for now
}
if (status !== 'active') return 'b2c_eu';
// Valid VAT number — check if same country as seller
return customerCountry === sellerCountry
? 'b2b_domestic'
: 'b2b_reverse_charge';
}Why VAT validation is the legal gate — not a UX nicety
Some teams implement VAT number fields at checkout but only do format validation — checking that the string looks like a German or French VAT number — without calling VIES. This is legally insufficient. A format-valid but VIES-invalid number means the customer is either not registered or has been deregistered. Applying zero-rate reverse charge to such a customer makes you liable for the VAT you failed to charge, because you did not take the required 'reasonable steps' to verify taxable status.
How the B2B/B2C decision affects your invoice fields
| Invoice field | B2B reverse charge | B2C (OSS) | Notes |
|---|---|---|---|
| Customer VAT number | Required | Not applicable | Must match the VIES-validated number |
| Tax rate shown | 0% | Customer country rate | B2C: rate from OSS rate table |
| VAT amount | €0 (reverse charge) | Charged and remitted | B2C amount goes to OSS return |
| 'Reverse charge' notation | Required | Not applicable | Explicit text on the invoice face |
| Article 196 reference | Required | Not applicable | "VAT reverse charge per Art. 196 EU VAT Dir." |
Handling edge cases
- →Customer in the same country as your seller entity: even with a valid VAT number, reverse charge does not apply to domestic supplies. Apply the standard domestic rate.
- →Customer provides a VAT number but it's for a different country than their billing address: validate against the country in the VAT number prefix (e.g. DE123... → validate as DE), not the billing country. VIES validates by prefix.
- →VIES returns service_unavailable at checkout: do not reject the customer. Allow the order, store the number as 'pending validation', and re-validate once VIES recovers. Document your service_unavailable handling policy for audit purposes.
- →Customer provides an EU VAT number but is purchasing as a consumer: this happens with sole traders. If VIES confirms the number is active, you may treat it as B2B. If the customer disputes a reverse-charge invoice, the liability shifts to them per Article 17 of Regulation 282/2011.
Frequently asked questions
- →**Can I trust the customer's claim that they are a business without validating?** No. Article 17 of EU Regulation 282/2011 requires the seller to take reasonable steps to verify taxable status. VIES validation is the standard way to satisfy this requirement.
- →**What if the customer gives a VAT number from a different EU country than their billing address?** Validate using the country code in the VAT number prefix. The billing address country is irrelevant for VIES lookup.
- →**Should I re-validate on every invoice or just at signup?** At minimum, re-validate monthly. Businesses deregister, and a stale validation creates the same liability as no validation. For subscription billing, re-validate before each monthly invoice generation.
Related resources
Start validating EU VAT numbers
Free plan — 100 validations/month. No credit card required.