EU VAT Reverse Charge: What Developers Need to Know
For ordinary cross-border B2B SaaS services, reverse charge makes the customer responsible for accounting for VAT. The supplier invoices without charging VAT. This guide explains the conditions and shows how to collect registration evidence without turning a VAT lookup into a tax decision.
What is the reverse charge?
Reverse charge changes who accounts for VAT. It is different from a statutory zero rate and from the intra-Community goods exemption in Article 138 of the VAT Directive. The customer accounts for output VAT and may deduct input VAT to the extent permitted by the applicable deduction rules.
When does the reverse charge apply?
For the services covered here, Article 44 normally places the supply where the business customer is established, or at the fixed establishment receiving the service. Article 196 makes the customer liable when the supplier is not established in that EU Member State. The supplier can be in another EU country or outside the EU, including the US or UK. Both parties do not have to be established in different EU Member States.
Establish the customer's taxable-person status and that it is acting as such, the establishment receiving the service, and the supplier's establishment position. A VAT number alone establishes none of these facts. A supplier's fixed establishment that does not intervene in the supply can be disregarded for liability purposes under Article 192a. The Commission also describes the case of a non-taxable legal entity registered for VAT. See the European Commission's persons liable for VAT guidance.
Domestic ordinary SaaS supplies normally follow domestic supplier-accounting rules. Specific domestic reverse charge regimes exist, so comparing two country codes is not a universal tax rule. Goods, property-related services, events, special schemes, exemptions and other place-of-supply exceptions need their own analysis and are outside this flow.
What VAT validation proves
VIES supplies registration evidence. Article 18 of Implementing Regulation 282/2011 describes evidence for customer status, including VAT-number confirmation and, where a customer has applied for a number but has not received it, other proof with reasonable verification. Contrary information and the capacity in which the customer buys still matter. Missing or invalid numbers are reasons to resolve the evidence, not an automatic finding that a customer is a consumer.
The January 2020 VAT-number condition for the intra-Community goods exemption must not be copied into a universal rule for services. Keep validation evidence with the transaction record, alongside your separate status, establishment and tax-treatment assessment. The EU guidance on VIES checks explains invalid results and recommends retaining a record of validation.
A registration-evidence flow for your backend
- Collect the customer's VAT number and business details. Route missing evidence for review.
- Request a fresh VIES check. Distinguish a completed invalid check from an unavailable check.
- Save the result, original timestamp, source and request ID, including any consultation number returned.
- Use that evidence in your separate assessment of customer status, establishment and the applicable rules.
The following self-contained TypeScript function runs server-side on Node.js 20 or later. Save it as registration-evidence.ts, set AVATCADO_API_KEY to your live API key, and import checkRegistration in your backend. It uses native fetch because the published Node SDK does not expose the fallback-control parameter. It calculates no VAT and never labels a customer B2C.
type Evidence = {
vat_number: string | null;
requested_at: string | null;
source: string | null;
source_status: string | null;
cached: boolean | null;
stale: boolean | null;
request_id: string | null;
consultation_number: string | null;
proof_status: "provided" | "not_provided";
};
type CheckResult = {
status: "Verified" | "Invalid" | "Unavailable" | "Error";
code?: string;
evidence: Evidence | null;
};
// Server-side Node.js 20+. This records registration evidence, not tax treatment.
export async function checkRegistration(
vatNumber: string,
requesterVatNumber?: string,
): Promise<CheckResult> {
const apiKey = process.env.AVATCADO_API_KEY;
if (!apiKey) return { status: "Error", code: "missing_api_key", evidence: null };
const normalize = (value: string) => value.toUpperCase().replace(/[\s.-]/g, "");
const vat = normalize(vatNumber);
if (!vat) return { status: "Error", code: "missing_parameter", evidence: null };
const url = new URL("https://api.avatcado.com/v1/validate");
url.searchParams.set("vat_number", vat);
url.searchParams.set("cache", "false");
url.searchParams.set("fallback", "false");
// Supply only a genuine requester VAT number. Non-EU sellers can omit it.
if (requesterVatNumber?.trim()) {
url.searchParams.set("requester_vat_number", normalize(requesterVatNumber));
}
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), 15_000);
let evidence: Evidence | null = null;
try {
const response = await fetch(url, {
headers: { Authorization: "Bearer " + apiKey },
signal: controller.signal,
});
const record = (value: unknown): Record<string, unknown> =>
value !== null && typeof value === "object" ? value as Record<string, unknown> : {};
const text = (value: unknown): string | null =>
typeof value === "string" && value.length > 0 ? value : null;
let body: Record<string, unknown>;
try {
body = record(await response.json());
} catch (error) {
if (controller.signal.aborted || !(error instanceof SyntaxError)) throw error;
return { status: response.status === 503 ? "Unavailable" : "Error",
code: response.status === 503 ? "http_503" : "malformed_response", evidence };
}
const data = record(body.data);
const meta = record(body.meta);
const error = record(body.error);
const consultation = text(data.consultation_number);
evidence = {
vat_number: text(data.vat_number), requested_at: text(data.requested_at),
source: text(meta.source), source_status: text(meta.source_status),
cached: typeof meta.cached === "boolean" ? meta.cached : null,
stale: typeof meta.stale === "boolean" ? meta.stale : null,
request_id: text(meta.request_id), consultation_number: consultation,
proof_status: consultation ? "provided" : "not_provided",
};
if (!response.ok || body.error !== undefined) {
const code = text(error.code) ?? "http_" + response.status;
const unavailable = response.status === 503 && (
code === "upstream_unavailable" || code === "upstream_member_state_unavailable" || code === "http_503"
);
return { status: unavailable ? "Unavailable" : "Error", code, evidence };
}
if (typeof data.valid !== "boolean" || data.vat_number !== vat ||
!evidence.requested_at || !Number.isFinite(Date.parse(evidence.requested_at))) {
return { status: "Error", code: "malformed_response", evidence };
}
// Without a requester, cache=false can still return outage cache. Check every response.
if (meta.source !== "vies" || meta.source_status !== "live" ||
meta.cached !== false || meta.stale !== false) {
return { status: "Unavailable", code: "fresh_check_unavailable", evidence };
}
return { status: data.valid ? "Verified" : "Invalid", evidence };
} catch (error) {
if (controller.signal.aborted) return { status: "Unavailable", code: "timeout", evidence };
if (error instanceof TypeError) return { status: "Unavailable", code: "network_error", evidence };
return { status: "Error", code: "unexpected_error", evidence };
} finally {
clearTimeout(timer);
}
}Call await checkRegistration(customerVatNumber), or pass your genuine requester VAT number as the second argument if you have one. A non-EU seller should omit that argument when it has no suitable VAT registration. Never substitute an invented number or an OSS/IOSS scheme identifier.
- Verified: an explicit live, noncached VIES response reports a valid registration.
- Invalid: an explicit live, noncached VIES response reports an invalid registration.
- Unavailable: a timeout, upstream outage, or response that cannot establish a fresh VIES check. Queue a retry or review.
- Error: input, authentication, quota or response errors. Preserve the code and resolve the operational issue.
These are application outcomes, not additional API statuses. Neither Invalid nor Unavailable determines the VAT rate. Give customers a way to correct their details and resolve the treatment before finalizing an invoice. Without a requester VAT number, an outage can still return stored evidence even with cache=false and fallback=false. Inspect the response metadata. An older consultation number must not be presented as proof of a new check.
Consultation numbers
A genuine requester VAT number allows VIES to return a consultation number where supported. Store it when supplied; it is not guaranteed. Missing proof is explicitly represented as consultation_number: nulland proof_status: "not_provided" in the example. A consultation number supports your record of a check, not a guarantee of the transaction's tax treatment.
Supplying requester_vat_number disables cache reads and national register fallback by default. With those defaults, an upstream outage returns a refunded 503 instead of a stored result. Explicit cache=true restores cache use, including stored outage results; fallback=true permits an eligible national register answer on a supported plan. Neither option guarantees a new consultation number. The example keeps both flags explicitly false and still checks the response metadata.
A request without a requester VAT number:
curl --max-time 15 "https://api.avatcado.com/v1/validate?vat_number=FR82542065479&cache=false&fallback=false" \
-H "Authorization: Bearer $AVATCADO_API_KEY"To request a consultation number, append &requester_vat_number=YOUR_GENUINE_VAT_NUMBER. This illustrative success response includes one; the field can be absent:
{
"data": {
"valid": true,
"vat_number": "FR82542065479",
"country_code": "FR",
"company": null,
"consultation_number": "WAPIAAAAA1BBB2",
"requested_at": "2026-09-15T10:00:00Z"
},
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"source": "vies",
"source_status": "live",
"cached": false,
"stale": false
}
}Invoice and reporting obligations
Once you have established that reverse charge applies, use the applicable invoice rules and the required reverse charge wording. For EU suppliers, the invoice normally includes both parties' VAT numbers; non-EU suppliers should check the applicable national requirements. EU recapitulative-statement obligations for relevant intra-EU services do not automatically apply to a US supplier. See the invoice requirements guide and the US SaaS guide.
Revalidation
Registrations and customer circumstances can change. Choose a documented revalidation policy for recurring billing and review changed details. A monthly or quarterly schedule is an operational choice, not a universal legal interval. Request fresh checks when your policy requires them, and retain the original timestamps of cached evidence. Cached calls still count toward your Avatcado monthly quota.
Get started
Avatcado's free tier includes 500 validations per month. Consultation numbers can be requested on all plans. Read the SaaS billing integration guide or the API documentation for integration details.
Frequently asked questions
Is VAT number validation legally required for the reverse charge?
For ordinary B2B services, a VAT check provides registration evidence within the customer-status assessment described in Article 18 of Implementing Regulation 282/2011. It does not independently determine business status, establishment or tax treatment. The January 2020 VAT-number condition for the intra-Community goods exemption is a separate rule and must not be applied universally to services. Keep the result and any consultation number with your assessment; resolve missing or contradictory evidence before finalizing the treatment.
Does the reverse charge apply to UK transactions after Brexit?
A UK supplier can fall under Article 196 when supplying ordinary B2B services taxable at an EU customer establishment, if the supplier is not established in that Member State. Sales to UK customers require the UK rules to be assessed separately. GB numbers validate through HMRC; XI numbers remain in VIES for Northern Ireland goods arrangements. A registry result alone does not establish the transaction treatment.
What is a consultation number and do I need one?
It is a reference returned by VIES where supported when a genuine requester VAT number is supplied. Retain it with the original result timestamp and source. Requester checks disable cache reads and national register fallback by default; explicit cache=true or fallback=true opts back into the corresponding path. If the upstream is unavailable with both paths disabled, the response is a refunded 503. A consultation number is not guaranteed, and a missing number should be recorded as missing. A non-EU supplier without a suitable requester VAT number can still validate the customer. Do not invent a requester or substitute an OSS/IOSS identifier. The reference supports evidence of a check, not a guarantee of tax treatment.
Can I apply the reverse charge for domestic transactions?
Ordinary domestic SaaS normally follows domestic supplier-accounting rules. However, national reverse charge regimes exist for specified supplies, so there is no universal rule based solely on matching country codes. Article 196 covers the services discussed here where the supplier is not established in the EU Member State of taxation. Check establishment, service type and applicable exceptions separately from VAT registration.
What should my reverse charge invoice include?
Use the applicable national invoice rules. For an EU supplier, Article 226 normally requires the relevant supplier and customer VAT numbers, names, addresses, dates and service particulars, with the reverse charge mention. Article 226a provides a simplification for qualifying non-established suppliers. Non-EU suppliers should check the rules applicable to their supply and should not invent an EU VAT number. See the reverse charge invoice requirements guide.
I'm a US SaaS company. Do I need to validate EU VAT numbers?
A US supplier can use VIES registration checks as evidence when assessing ordinary B2B services to EU customers. Article 196 does not require the supplier to be established in another EU Member State. Establish customer status and capacity, the receiving establishment and the supplier establishment position separately. A missing or invalid number needs resolution; it does not automatically classify the customer as B2C. The US SaaS guide explains the scoped flow.
What happens if the customer's VAT number is invalid?
Check for a typo, a pending registration or other evidence that needs resolution. Distinguish a completed live invalid result from an unavailable service. Neither result alone establishes the correct tax rate or automatic supplier liability. Assess the facts of the supply and correct invoices when the applicable rules require it. A number becoming invalid later does not itself show that an earlier invoice was wrong.
How often should I revalidate a customer's VAT number?
Choose a documented schedule appropriate to your recurring billing and review changed customer details. Monthly or quarterly checks are operational choices, not a universal legal deadline. When your policy needs a fresh VIES check, request cache=false and fallback=false and inspect source, source_status, cached and stale. Without a requester, an outage can still return stored evidence even with cache=false; retain its original timestamp. Requester checks disable cache and fallback by default, with explicit true flags opting back in. Invalid or unavailable results should trigger review or retry, not an automatic change of tax rate.
Sources
- Persons liable for VAT European Commission, accessed September 15, 2026
- VAT Directive, Articles 44, 138, 192a, 196, 219a, 226, 226a and 262 EUR-Lex, accessed September 15, 2026
- Implementing Regulation 282/2011, Articles 18 and 19 EUR-Lex, accessed September 15, 2026
- Check a VAT number (VIES) European Union, accessed September 15, 2026
Try it on a real VAT number
Check any VAT or GST number against the official registry for free, no account needed.
Related guides
How to Handle VAT Validation in Your SaaS Billing Flow
Learn how to integrate real-time VAT validation into your SaaS checkout flow. Covers reverse charge logic, Stripe integration, and storing validation proof.
EU VAT Validation for US SaaS Companies
How US SaaS suppliers collect EU VAT registration evidence and assess ordinary B2B reverse charge, customer status and consumer-sales obligations.
Validate EU VAT Numbers via API: Developer Guide
Learn how to validate EU VAT numbers, plus UK, Swiss, Norwegian, and Australian VAT/GST, via REST API. Covers VIES, HMRC, TypeScript, Python, and test mode.
VAT Validation for Stripe Users: Coverage Gaps
Stripe validates EU, UK, and AU tax IDs but skips Swiss, Norwegian, and 100+ other types. See where Stripe falls short and how Avatcado fills the gaps.
Do OSS and IOSS Numbers Show Up in VIES?
OSS and IOSS registration numbers cannot be checked in VIES. What VIES covers, why IM-prefixed IOSS numbers are not public, and what to validate instead.
EU Reverse Charge Invoice Requirements
Required fields on an EU reverse charge invoice: both VAT numbers, the exact 'Reverse charge' wording, and what to do if the buyer's VAT number is invalid.