Validate Italian Partita IVA
Validate Italian Partita IVA numbers for B2B transactions. Includes local checksum validation (Luhn algorithm) and VIES lookup for active registration status.
Italian Partita IVA numbers consist of the IT prefix followed by exactly 11 digits (e.g. IT12345678901). The first 7 digits identify the business, the next 3 digits identify the province of registration (a value between 001 and 100, plus special codes 120, 121, and 999 for certain entities), and the final digit is a check digit computed using a Luhn-variant algorithm. This local checksum validation catches transposition errors before they reach the VIES network.
The Luhn-variant for Italian VAT works as follows: sum the digits in odd positions (1, 3, 5, 7, 9) as-is; for digits in even positions (2, 4, 6, 8, 10), double each digit — if the result is 10 or more, subtract 9; sum all values; the check digit (position 11) is (10 - (total mod 10)) mod 10. If a provided number fails this check, reject it immediately without calling the TaxID API, since VIES will also reject it and the API call would be wasted.
The Agenzia delle Entrate submits Italian Partita IVA registrations to VIES. The Italian VIES node is generally reliable but returns only the registered status without company name or address for many Italian entities, unlike some other EU member states. When company_name is null in the TaxID response, fall back to displaying the validated Partita IVA number as confirmation rather than showing a blank field, and consider supplementing with a lookup against the Italian Business Register (Registro delle Imprese) if full company details are required.
Implementation steps
- 1
Validate 11-digit IT format
Strip the IT prefix and any spaces, then confirm the remainder is exactly 11 numeric digits using /^[0-9]{11}$/. Additionally, check that digits 8–10 (the province code, 0-indexed) form a value between 001 and 100 inclusive or match the special codes 120, 121, or 999; province codes outside this range indicate a malformed number that should be rejected before the checksum step.
- 2
Run Luhn checksum locally
Implement the Italian VAT Luhn variant: iterate over the first 10 digits; for odd positions (1,3,5,7,9, 1-indexed), add the digit directly; for even positions (2,4,6,8,10), double it and subtract 9 if the result is ≥ 10; sum all values and compute (10 - (sum mod 10)) mod 10; compare to digit 11. Reject numbers where the check digit does not match before calling GET /api/v1/validate/IT/:vatNumber, as this eliminates a significant proportion of typo-induced invalid API calls.
- 3
Query VIES for active status
After passing local format and checksum checks, call GET /api/v1/validate/IT/:vatNumber. The TaxID API queries the Agenzia delle Entrate's VIES node. A status: 'active' response confirms the Partita IVA is registered for EU intra-community transactions and that reverse-charge treatment under Article 196 of the VAT Directive applies. A status: 'invalid' means the number exists in Italian records but is not currently active in VIES — the business may be newly registered, suspended, or operating only domestically.
- 4
Handle Agenzia delle Entrate response
The Italian VIES node frequently returns a valid status without accompanying company_name or company_address data. Handle null values gracefully: display 'Partita IVA verified' with the validated number when company_name is null, rather than showing a blank confirmation. For invoicing, source the legal company name from an alternative Italian business register API (e.g. Registro delle Imprese via Infocamere) if required for invoice compliance under DPR 633/1972.
Code example
Node.js
const res = await fetch(
'http://localhost:3000/api/v1/validate/DE/IT12345678901',
{ headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
const { valid, status, company_name, company_address } = await res.json();
if (valid) {
console.log(`Valid EU business: ${company_name}`);
} else if (status === 'service_unavailable') {
// VIES is temporarily down — retry or allow with manual check
console.log('VIES unavailable — check back in a few minutes');
} else {
console.log('Invalid VAT number — charge local tax rate');
}Python
import requests
res = requests.get(
"http://localhost:3000/api/v1/validate/DE/IT12345678901",
headers={"Authorization": "Bearer YOUR_API_KEY"}
)
data = res.json()
if data["valid"]:
print(f"Valid: {data['company_name']}")
elif data["status"] == "service_unavailable":
print("VIES temporarily unavailable")
else:
print("Invalid VAT number")API response
The TaxID API returns a consistent JSON response for every validation request:
{
"valid": true,
"status": "active",
"country_code": "DE",
"vat_number": "123456789",
"company_name": "Example GmbH",
"company_address": "Musterstraße 1, 10115 Berlin",
"request_date": "2026-05-10T00:00:00.000Z",
"cached": false,
"request_id": "req_01j..."
}Error handling
The API uses a consistent Stripe-style error format. Always handle service_unavailable separately — VIES has occasional downtime and you should not reject valid customers during outages.
activeVAT number is valid and the business is registered
invalidVAT number format is wrong or not registered in VIES
service_unavailableVIES or the national system is temporarily down — retry later
Country-specific guides
Further reading
Italian VAT Number Validation: Partita IVA Format, VIES, and Code Examples
Italian Partita IVA numbers follow IT + 11 digits. The last digit is a computed check digit, and Italy's VIES endpoint i…
EU VAT Number Validation: The Complete Developer Guide (2026)
VIES is SOAP-based, unreliable, and has no caching. This guide explains how EU VAT validation works end-to-end, how to h…
Evaluating EU VAT APIs? Compare TaxID with:
Related use cases
EU VAT compliance for SaaS billing
Handle EU VAT for SaaS subscriptions. Validate customer VAT numbers at signup, determine B2B vs B2C ...
DAC7 marketplace seller VAT verification
Verify seller VAT numbers during marketplace onboarding for DAC7 compliance. EU platforms must colle...
Bulk VAT number validation via CSV import
Validate hundreds of EU VAT numbers in batch using parallel API requests. Ideal for CRM data cleansi...