Home / Use cases / Node.js

Node.js

Node.js VAT API — EU VAT Validation in Node.js

Node.js VAT API integration guide: implement EU VAT number validation in a Node.js or Express application using the TaxID REST API. Includes TypeScript types, error handling for VIES downtime, and caching strategy.

Node.js's native fetch (available since v18 without flags, and polyfillable with node-fetch in earlier versions) is sufficient to call the TaxID REST API. The API returns a consistent JSON shape — { valid, status, company_name, company_address, cached, request_id } — that maps cleanly to a TypeScript interface, giving you type-safe access to validation results throughout your application.

VIES, the underlying EU SOAP service, can return status: 'service_unavailable' for specific member-state nodes without any HTTP error code — the TaxID API normalises this into the status field so your code does not need to parse SOAP faults. Your error-handling logic should branch on three cases: 'active' (proceed), 'invalid' (reject the VAT number), and 'service_unavailable' (treat as a temporary error and retry or fail open with a warning).

For high-throughput Node.js services, caching TaxID results in Redis with a TTL matching the API's own cache window (86400 seconds for active numbers, 3600 seconds for invalid) lets you serve sub-millisecond responses for repeat lookups without consuming API quota. Use the composite key `vat:${country}:${vatNumber}` and store the full response JSON so every consumer has access to company_name and request_id without a round-trip.

Implementation steps

  1. 1

    Install node-fetch or use native fetch

    In Node.js 18+ no installation is needed — global fetch is available by default. For Node.js 16 or earlier, add node-fetch v3 (ESM) or v2 (CJS) to your project. Avoid the deprecated node-fetch v1 or the unmaintained isomorphic-fetch package; they lack proper error handling for network timeouts, which matters when VIES member-state nodes are slow.

  2. 2

    Create validateVAT helper function

    Write an async function that accepts (country: string, vat: string) and calls GET https://api.taxid.pro/v1/validate/${country}/${vat} with an Authorization: Bearer YOUR_API_KEY header. Type the return value as { valid: boolean; status: 'active' | 'invalid' | 'service_unavailable'; company_name: string | null; company_address: string | null; cached: boolean; request_id: string } so callers get compile-time safety on every field.

  3. 3

    Add error handling for VIES unavailability

    Check the status field before using the result: throw a retriable VATServiceUnavailableError when status === 'service_unavailable' so upstream callers (Express middleware, queue workers) can decide whether to retry or fail open. Never silently treat service_unavailable as valid — doing so would zero-rate invoices for customers whose VAT numbers were never actually confirmed with VIES.

  4. 4

    Cache results in Redis or memory

    After a successful API call, store the JSON-serialised response in Redis with SETEX vat:${country}:${vat} 86400 <json> for active numbers and SETEX vat:${country}:${vat} 3600 <json> for invalid ones; these TTLs match TaxID's own cache policy. For single-server deployments without Redis, a simple in-process Map with a timestamp-based eviction check is an acceptable lightweight alternative.

Code example

Node.js

const res = await fetch(
  'http://localhost:3000/api/v1/validate/DE/DE123456789',
  { 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/DE123456789",
    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

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

Stripe EU VAT: Validate Tax IDs Before Charging Customers

Stripe EU VAT integration guide: validate EU VAT numbers server-side before applying zero-rate B2B e...

UK VAT validation in Shopify B2B

Validate UK VAT numbers for B2B customers in Shopify. Required under UK Making Tax Digital rules for...

WooCommerce Spain NIF/CIF validation

Validate Spanish NIF and CIF numbers in WooCommerce checkout. Automatically apply B2B tax exemptions...