API Reference

Vatnode is a single-endpoint REST API that validates EU VAT numbers and returns the official VIES consultation number — the timestamped proof EU tax authorities accept at audit.

Base URL: https://vatnode.com

All requests and responses use JSON. All endpoints require HTTPS.

⚠️ Early access: The API is live for design partners. Join the waitlist to get credentials.

Authentication

Vatnode uses an API key passed in the x-api-key header. Include your key in every request:

HTTP header
x-api-key: YOUR_API_KEY

Get your API key by joining the waitlist. Keys are issued per account and tied to your plan quota. Keep your key secret — never expose it in client-side code or public repos.

Quickstart

Validate a VAT number in one call. Most integrations are live in under an hour.

cURL
JavaScript
Python
PHP
# Validate an Irish VAT number curl -X POST https://vatnode.com/v1/validate \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"vat_number":"IE6388047V","requester_vat":"NL123456789B01"}'
const response = await fetch('https://vatnode.com/v1/validate', { method: 'POST', headers: { 'x-api-key': 'YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ vat_number: 'IE6388047V', requester_vat: 'NL123456789B01' // optional but recommended }) }); const result = await response.json(); console.log(result.consultationNumber); // "WAPIAAAAW1234567"
import requests response = requests.post( 'https://vatnode.com/v1/validate', headers={'x-api-key': 'YOUR_API_KEY'}, json={ 'vat_number': 'IE6388047V', 'requester_vat': 'NL123456789B01' } ) result = response.json() print(result['consultationNumber']) # "WAPIAAAAW1234567"
$ch = curl_init('https://vatnode.com/v1/validate'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'x-api-key: YOUR_API_KEY', 'Content-Type: application/json', ]); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([ 'vat_number' => 'IE6388047V', 'requester_vat' => 'NL123456789B01', ])); $result = json_decode(curl_exec($ch), true); echo $result['consultationNumber']; // "WAPIAAAAW1234567"

POST /v1/validate

Validates an EU VAT number and returns the official VIES consultation number — the timestamped proof that you checked a customer's VAT ID against the EU's system.

Coverage: the EU-27 via VIES, plus non-VIES countries via their national registries — Norway (Brønnøysund) live now, Switzerland next. National-registry results return company name and address; consultationNumber is VIES-only.

POST https://vatnode.com/v1/validate

Request body

ParameterTypeRequiredDescription
vat_numberstringrequiredThe VAT number to validate. Include the 2-letter country prefix (e.g. DE811907980, NL123456789B01). Spaces and hyphens are stripped automatically.
requester_vatstringoptionalYour own VAT number. Strongly recommended — required by VIES to generate a consultation number with full legal weight.

Example response — success

JSON · 200 OK
{ "valid": true, "vatNumber": "IE6388047V", "countryCode": "IE", "consultationNumber": "WAPIAAAAW1234567", "name": "GOOGLE IRELAND LIMITED", "address": "3RD FLOOR, GORDON HOUSE, BARROW STREET, DUBLIN 4", "requestDate": "2026-06-25+02:00", "timestamp": "2026-06-25T14:22:03.000Z" }

name and address are returned as published by each member state. Germany and Spain release validity only (empty strings) — that is VIES policy for those states, not a gap in the API. Full breakdown in Country coverage.

Example response — invalid VAT

JSON · 200 OK
{ "valid": false, "vatNumber": "DE000000000", "countryCode": "DE", "consultationNumber": "", "name": "", "address": "", "requestDate": "2026-06-25+02:00", "timestamp": "2026-06-25T14:22:10.000Z" }

When VIES is unavailable

VIES has frequent per-country outages. When the relevant member-state database is down, the API returns {"error":"vies_unavailable","retryable":true} rather than a misleading valid:false — so you can implement a short retry with exponential backoff instead of wrongly rejecting a real customer. Live per-country status is on the VIES status page.

Is there a fallback when a country's VIES is down? There's no way to run a fresh validity check without VIES — it's the single official gateway to the 27 national registers, so when a state's node is offline it is offline for everyone. What we do offer is honest and clearly labelled: if your own key validated that exact VAT number in the last 24 hours, then during an outage we return your last confirmed result flagged source: "cache" with cached: true and the original cachedAt timestamp — so your checkout or billing flow doesn't break — and you retry for a fresh consultation number once VIES recovers. We never pass cached or third-party data off as a fresh check. For countries VIES doesn't cover at all, we query national registers directly — Norway is live, Switzerland is next. Live per-country status: status page.

Country coverage — what each country returns

Every validation for the 27 EU member states + Northern Ireland (XI) confirms validity and, when you pass requester_vat, returns the official consultation number — always. Two things vary by country: whether the company name & address is released, and what happens if that country's VIES node goes down. The national-register fallback (green) is live where a country publishes a free official register.

CodeCountryName & addressIf VIES is down
ATAustria24h cache1
BEBelgium24h cache1
BGBulgaria24h cache1
HRCroatia24h cache1
CYCyprus24h cache1
CZCzechiaLive register · ARES2
DKDenmarkLive register · CVR2
EEEstonia24h cache1
FIFinlandLive register · PRH2
FRFranceLive register · SIRENE2
DEGermany— validity only324h cache1
ELGreece (EL5)24h cache1
HUHungary24h cache1
IEIreland24h cache1
ITItaly24h cache1
LVLatvia24h cache1
LTLithuania24h cache1
LULuxembourg24h cache1
MTMalta24h cache1
NLNetherlands24h cache1
PLPolandLive register · White List2
PTPortugal24h cache1
RORomania24h cache1
SKSlovakia24h cache1
SISlovenia24h cache1
ESSpain— validity only324h cache1
SESweden24h cache1
XINorthern Ireland24h cache1
NONorway · non-VIESNational register is the source4

Notes — how to read this table

Every EU-27 + XI row returns validity + the official VIES consultation number whenever you pass your own requester_vat — that's the audit evidence auditors ask for, and it's constant across every country here. Only the two columns above differ.

1 Standard fallback (24h cache). If a country's VIES node is down, we return your key's own last confirmed check from the past 24 hours, flagged source: "cache" — so your checkout keeps working and you keep the real consultation number. Retry for a fresh one when VIES recovers.

2 Live national-register fallback (FR, PL, FI, CZ, DK). These states publish a free official register, so during a VIES outage we confirm the number against it live — France (SIRENE), Poland (VAT White List), Finland (PRH), Czechia (ARES), Denmark (CVR). Flagged source: "national_vat_register_pl" etc.; it honestly carries consultationNumber: null, because a national register doesn't issue one. Romania is next.

3 Germany (DE) & Spain (ES) release validity only. name and address come back empty for these two — it's their national policy, not a gap in the API. Every other state returns the registered company name and address.

4 Norway (NO) is not part of VIES. We validate it directly against the Brønnøysund national register (name + address; no consultation number, as that's a VIES-only concept). Switzerland (CH) is next.

5 Greece uses the EL prefix in VIES (its ISO code is GR). We never present cached or third-party data as a fresh live check.

Disclosure policy can change; we verify continuously and this table reflects live behaviour. Try any country yourself with the free checker.

The three response shapes

Same endpoint, same fields — only what each source releases differs. Check for error first, then read valid.

1. Most EU-27 — validity + consultation number + name + address:

JSON · 200 OK
{ "valid": true, "vatNumber": "IE6388047V", "countryCode": "IE", "name": "GOOGLE IRELAND LIMITED", "address": "GORDON HOUSE, BARROW STREET, DUBLIN 4", "consultationNumber": "WAPIAAAAW1234567", "requestDate": "2026-07-06+02:00", "timestamp": "2026-07-06T10:14:02.000Z" }

2. Germany & Spain — validity + consultation number; name/address empty (state releases validity only):

JSON · 200 OK
{ "valid": true, "vatNumber": "DE811907980", "countryCode": "DE", "name": "", // Germany discloses validity only "address": "", "consultationNumber": "WAPIAAAAW7654321", // still issued — this is your audit proof "requestDate": "2026-07-06+02:00", "timestamp": "2026-07-06T10:14:05.000Z" }

3. Non-VIES country (Norway) — validity + name + address from the national register; no consultation number (VIES-only concept), but the check is recorded in your audit log:

JSON · 200 OK
{ "valid": true, "vatNumber": "NO923609016", "countryCode": "NO", "name": "EQUINOR ASA", "address": "Forusbeen 50, 4035, STAVANGER, NO", "consultationNumber": "", // VIES-only; recorded in /v1/log instead "source": "national_registry_no", "requestDate": "2026-07-06T10:14:09.000Z", "timestamp": "2026-07-06T10:14:09.000Z" }

4. During a VIES outage (cache fallback) — if your key checked this exact VAT in the last 24h, we serve that last confirmed result flagged as cached, so your flow doesn't break. Retry for a fresh consultation number when VIES recovers:

JSON · 200 OK
{ "valid": true, "vatNumber": "DE811907980", "countryCode": "DE", "consultationNumber": "WAPIAAAAW7654321", // from your prior confirmed check "source": "cache", "cached": true, "cachedAt": "2026-07-06T09:02:00.000Z", // when the cached check actually ran "timestamp": "2026-07-06T10:14:12.000Z" }

Cache only ever serves your own key's prior confirmed check for the same VAT, within 24h — never third-party data, and always flagged. If there's no recent cached check, you get vies_unavailable to retry.

GET /v1/log Beta

Returns the validation history for your API key — every check is logged server-side, so this is your audit trail. Pass your key in the x-api-key header, same as /v1/validate.

GET https://vatnode.com/v1/log
ParameterTypeDescription
limitintegerNumber of records to return, newest first. Default: 100. Max: 1000.

Example response

JSON · 200 OK
{ "ok": true, "key": "vnd-…", "count": 128, "month_used": 12, "validations": [ { "vat_number": "DE811907980", "requester_vat": "NL123456789B01", "valid": true, "consultation_number": "WAPIAAAAW1234567", "request_date": "2026-07-06T19:07:58Z", "created_at": "2026-07-06T19:07:58Z" } ] }

CSV export and date-range filtering are on the roadmap — email us if you need them now.

Response schema

All responses return HTTP 200 with a JSON body. Check the valid field and the presence of error to determine success or failure.

FieldTypeDescription
validbooleanWhether the VAT number is active and registered.
vatNumberstringThe VAT number that was validated.
countryCodestringISO 3166-1 alpha-2 country code derived from the VAT number prefix.
consultationNumberstringThe official VIES consultation number (e.g. WAPIAAAAW1234567). Empty string when VAT is invalid or VIES is unavailable.
namestringRegistered company name as returned by VIES. Empty string when unavailable.
addressstringRegistered company address as returned by VIES. Empty string when unavailable.
requestDatestringDate of the VIES query (YYYY-MM-DD+offset).
timestampstringISO 8601 timestamp of when the validation was performed.

Error codes

All responses return HTTP 200. When an error occurs, the response body contains an error field. Check for this before reading validation results.

Error codeDescription
invalid_api_keyMissing or invalid API key. Pass your key in the x-api-key header.
vies_unavailableVIES is temporarily down. retryable: true is included — implement exponential backoff.

Error response shape

JSON · 200 OK
{ "error": "invalid_api_key", "message": "Missing or invalid API key. Pass your key in the x-api-key header.", "docs": "https://vatnode.com/docs" }

Rate limits & quotas

Each API key has a monthly validation quota, enforced per key: Free 100 · Starter 2,000 · Growth 10,000 · Scale 50,000 (see the pricing page).

When a key exceeds its monthly quota, the API returns an error body instead of a validation result:

JSON
{ "error": "rate_limit_exceeded", "message": "Monthly limit of 100 validations reached on the free plan. Upgrade at https://vatnode.com/pricing", "limit": 100, "used": 101, "docs": "https://vatnode.com/docs" }

Check for the error field before reading validation results. Need a higher quota for evaluation? Email us and we'll raise your key's limit.

SDKs & libraries

Lightweight, dependency-free clients for Node.js, Python, and PHP are available now. Each wraps /v1/validate and /v1/log so you don't hand-roll HTTP.

Node.js
const Vatnode = require('./vatnode'); const vn = new Vatnode(process.env.VATNODE_KEY); const r = await vn.validate('DE811907980', 'NL123456789B01'); console.log(r.valid, r.consultationNumber);
Python
from vatnode import Vatnode vn = Vatnode(os.environ["VATNODE_KEY"]) r = vn.validate("DE811907980", "NL123456789B01") print(r["valid"], r["consultationNumber"])

Dependency-free clients for Node.js, Python and PHP are on GitHub: github.com/acirema792/vatnode-sdks. Need Ruby, Go, or a WooCommerce / Shopify plugin? Tell us →

MCP server New

Validate VAT numbers — with consultation numbers — directly inside Claude Desktop, Cursor, or any MCP-compatible AI client. Published on npm as vies-mcp.

claude_desktop_config.json
{ "mcpServers": { "vies": { "command": "npx", "args": ["-y", "vies-mcp"], "env": { "VATNODE_API_KEY": "vnd-your-key-here" } } } }

Tools: validate_vat (validity + company data + consultation number) and vies_status (live per-country VIES availability). Source: github.com/acirema792/vies-mcp.

Changelog

2026-07-17 — MCP server + country coverage

vies-mcp published on npm — VAT validation inside any MCP-compatible AI client. New country coverage reference documenting exactly what each member state returns. Docs examples switched to an Irish VAT number so the sample response matches real VIES behavior (DE/ES release validity only).

2026-06-25 — Early access

Initial API release for design partners. Endpoint: POST /v1/validate. VIES consultation number capture + company enrichment for all 27 EU member states. API key auth via x-api-key header.