Home / Use cases / Custom

Custom

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. 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. 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. 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. 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:

200 OK (active)valid
{
  "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.

active

VAT number is valid and the business is registered

invalid

VAT number format is wrong or not registered in VIES

service_unavailable

VIES or the national system is temporarily down — retry later

Country-specific guides

Further reading

Evaluating EU VAT APIs? Compare TaxID with:

Ready to implement?

Get your free API key and start validating EU VAT numbers today.

Get free API key

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...