A VAT validation API is a programmable interface that lets your application check whether a VAT (Value Added Tax) or Tax ID number is legitimately registered with a government tax authority — in real time, without manual lookup. You send a VAT number; the API returns a structured response telling you whether it is active, who it belongs to, and their registered address. The whole round-trip takes under two seconds.
For any SaaS company billing B2B customers across EU borders, this check is not optional. EU VAT Directive 2006/112/EC requires sellers to verify their buyer's VAT registration before applying zero-rate treatment (the reverse charge mechanism). Skip it and you become personally liable for the full VAT amount on every incorrectly zero-rated invoice — regardless of whether the buyer gave you a plausible-looking number.
What Does a VAT Validation API Actually Do?
Under the hood, a VAT validation API does two things in sequence. First, it checks the format of the number you submitted against the country-specific pattern (Germany: DE + 9 digits; France: FR + 2 alphanumeric chars + 9 digits; Netherlands: NL + 9 digits + B + 2 digits). This catches most user input errors instantly with no network call. Second, it queries the live official registry — in the EU, that is VIES (the VAT Information Exchange System), operated by the European Commission. In the UK it is HMRC, in Australia it is the ABR, in Norway it is Brønnøysund.
VIES is a federation of 27 national databases — not a single registry. When you validate a German VAT number, VIES routes the query to Germany's BZST (Bundeszentralamt für Steuern) and relays the response. A French TVA number goes to the DGFiP. This architecture means individual country nodes can be temporarily unavailable without the whole system going down, but it also means response times and reliability vary by country. A good VAT API wraps this complexity: it handles SOAP-to-JSON translation, retries transient failures, caches results to reduce latency, and returns consistent status codes regardless of which country you are validating.
The API Response: What You Get
// GET /api/v1/validate/DE/DE123456789
{
"valid": true,
"status": "active",
"vat": "DE123456789",
"country_code": "DE",
"company_name": "Example GmbH",
"address": "Musterstraße 1, 10115 Berlin, Germany",
"cached": false,
"request_id": "req_01j9kx8a..."
}
// Invalid number
{
"valid": false,
"status": "invalid",
"vat": "DE000000000",
"country_code": "DE",
"company_name": null,
"address": null,
"cached": false,
"request_id": "req_01j9ky..."
}
// VIES temporarily unavailable — NOT the same as invalid
{
"valid": false,
"status": "service_unavailable",
"vat": "IT12345678901",
"country_code": "IT",
"company_name": null,
"address": null,
"cached": false,
"request_id": "req_01j9kz..."
}| Field | Type | What it means |
|---|---|---|
| valid | boolean | true only when VIES confirmed the number is actively registered |
| status | string | active | invalid | inactive | format_invalid | service_unavailable |
| company_name | string | null | Business name from the official registry (some countries redact this) |
| address | string | null | Registered address from VIES (some countries redact) |
| cached | boolean | true if served from cache (sub-10ms); false if a live VIES call was made |
| request_id | string | Unique identifier — include in audit logs and support tickets |
Warning
Never treat `status: service_unavailable` the same as `status: invalid`. A service_unavailable response means VIES could not be reached — the number may be perfectly valid. Charge standard VAT and refund once VIES recovers; do not silently zero-rate an unverified number.
Why SaaS Companies Need This
SaaS companies selling to EU businesses face three compounding problems without automated VAT validation. First, EU VAT law creates direct financial liability: if a customer provides an invalid VAT number and you zero-rate their invoice, the VAT amount is owed by your company — not the customer. EU tax authorities run automated cross-checks between VIES and VAT returns. The bigger your zero-rated invoice volume, the higher your audit exposure.
Second, the problem does not go away at signup. VAT registrations change — businesses deregister voluntarily, get cancelled by tax authorities, or restructure across borders. A number that was valid when the customer signed up may be revoked on the day you issue your 12th monthly invoice. Subscription businesses need re-validation on a recurring schedule, not just at onboarding.
Third, the company name and address returned by the API are a free fraud-detection signal. When a customer claims to be a large German Mittelstand company but the VIES-registered address is a residential flat in a small town, that discrepancy is worth a manual review before extending credit terms or activating a high-volume plan.
When Is VAT Validation Legally Required?
EU VAT Directive 2006/112/EC Article 138 makes VIES validation a prerequisite for applying zero-rate to intra-community B2B supplies. This applies whenever you sell to a business in a different EU member state and wish to apply reverse-charge. 'Reasonable steps' to verify the VAT number — meaning a VIES check, not just accepting the buyer's word — must be documented. Without that documentation, your zero-rated invoices are vulnerable to reclassification during audit.
For marketplace platforms, DAC7 (EU Directive 2021/514) adds a separate layer. Platforms facilitating transactions between sellers and buyers must collect and verify seller VAT numbers if the seller earns over €2,000 or completes 30+ transactions per year, with annual reporting to national tax authorities.
Outside the EU: the UK requires VAT validation under HMRC rules for zero-rated UK-EU supplies post-Brexit. Australia's GST system, Norway's VAT system, and Singapore's GST system all have equivalent requirements for B2B cross-border supplies. The TaxID API covers 31 countries across these jurisdictions with a single endpoint.
B2B vs B2C: Why It Only Matters for B2B
VAT validation is a B2B concern, not a B2C concern. If you sell to a consumer (someone without a VAT number), you charge VAT at the applicable rate in their country — no validation step needed. The reverse charge mechanism that makes zero-rating possible only applies to transactions between two VAT-registered businesses. This means your checkout flow only needs to trigger the validation API when the customer indicates they are a business and provides a VAT number. If they leave the VAT number field blank, treat them as a consumer and apply standard VAT.
How to Choose a VAT Validation API
| Criteria | What to look for |
|---|---|
| Country coverage | All 27 EU member states via VIES minimum. UK (HMRC), Australia (ABR), Norway, Switzerland for global SaaS. |
| Status codes | Explicit service_unavailable vs invalid distinction. Do not use APIs that collapse both into a single false response. |
| Response fields | company_name and address for fraud detection and audit trail. request_id for support. |
| Caching | Redis-backed caching for sub-10ms responses on repeated lookups. VIES has rate limits. |
| Uptime | VIES is unreliable. The API should handle member-state outages gracefully and document its SLA. |
| Pricing | Per-request pricing with a free tier for development. Flat monthly plans get expensive at scale. |
| Documentation | Code examples in your language. Clear error taxonomy. Sandbox for testing invalid/unavailable states. |
Making Your First Request
# Validate a German VAT number
curl https://taxid.dev/api/v1/validate/DE/DE123456789 \
-H "Authorization: Bearer YOUR_API_KEY"
# Validate a UK VAT number
curl https://taxid.dev/api/v1/validate/GB/GB123456789 \
-H "Authorization: Bearer YOUR_API_KEY"
# Get your API key at https://taxid.dev/signup — free tier includes 100 requests/monthasync function validateVAT(country: string, vat: string) {
const res = await fetch(
`https://taxid.dev/api/v1/validate/${country}/${vat}`,
{ headers: { Authorization: `Bearer ${process.env.TAXID_API_KEY}` } }
);
const data = await res.json();
if (data.status === 'active') return { valid: true, name: data.company_name };
if (data.status === 'service_unavailable') throw new Error('VAT registry temporarily unavailable');
return { valid: false, name: null };
}For a complete integration walkthrough covering frontend UX, server-side validation, Stripe zero-rate application, and recurring re-validation, see How to Integrate a VAT Number Check API into Your Checkout Flow. For country-specific format details and regex patterns for all 27 EU member states plus UK and Australia, see the VAT API country pages.