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.
Vatnode uses an API key passed in the x-api-key header. Include your key in every request:
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.
Validate a VAT number in one call. Most integrations are live in under an hour.
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.
| Parameter | Type | Required | Description |
|---|---|---|---|
| vat_number | string | required | The VAT number to validate. Include the 2-letter country prefix (e.g. DE811907980, NL123456789B01). Spaces and hyphens are stripped automatically. |
| requester_vat | string | optional | Your own VAT number. Strongly recommended — required by VIES to generate a consultation number with full legal weight. |
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.
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.
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.
| Code | Country | Name & address | If VIES is down |
|---|---|---|---|
| AT | Austria | ✓ | 24h cache1 |
| BE | Belgium | ✓ | 24h cache1 |
| BG | Bulgaria | ✓ | 24h cache1 |
| HR | Croatia | ✓ | 24h cache1 |
| CY | Cyprus | ✓ | 24h cache1 |
| CZ | Czechia | ✓ | Live register · ARES2 |
| DK | Denmark | ✓ | Live register · CVR2 |
| EE | Estonia | ✓ | 24h cache1 |
| FI | Finland | ✓ | Live register · PRH2 |
| FR | France | ✓ | Live register · SIRENE2 |
| DE | Germany | — validity only3 | 24h cache1 |
| EL | Greece (EL5) | ✓ | 24h cache1 |
| HU | Hungary | ✓ | 24h cache1 |
| IE | Ireland | ✓ | 24h cache1 |
| IT | Italy | ✓ | 24h cache1 |
| LV | Latvia | ✓ | 24h cache1 |
| LT | Lithuania | ✓ | 24h cache1 |
| LU | Luxembourg | ✓ | 24h cache1 |
| MT | Malta | ✓ | 24h cache1 |
| NL | Netherlands | ✓ | 24h cache1 |
| PL | Poland | ✓ | Live register · White List2 |
| PT | Portugal | ✓ | 24h cache1 |
| RO | Romania | ✓ | 24h cache1 |
| SK | Slovakia | ✓ | 24h cache1 |
| SI | Slovenia | ✓ | 24h cache1 |
| ES | Spain | — validity only3 | 24h cache1 |
| SE | Sweden | ✓ | 24h cache1 |
| XI | Northern Ireland | ✓ | 24h cache1 |
| NO | Norway · non-VIES | ✓ | National 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.
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:
2. Germany & Spain — validity + consultation number; name/address empty (state releases validity only):
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:
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:
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.
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.
| Parameter | Type | Description |
|---|---|---|
| limit | integer | Number of records to return, newest first. Default: 100. Max: 1000. |
CSV export and date-range filtering are on the roadmap — email us if you need them now.
All responses return HTTP 200 with a JSON body. Check the valid field and the presence of error to determine success or failure.
| Field | Type | Description |
|---|---|---|
| valid | boolean | Whether the VAT number is active and registered. |
| vatNumber | string | The VAT number that was validated. |
| countryCode | string | ISO 3166-1 alpha-2 country code derived from the VAT number prefix. |
| consultationNumber | string | The official VIES consultation number (e.g. WAPIAAAAW1234567). Empty string when VAT is invalid or VIES is unavailable. |
| name | string | Registered company name as returned by VIES. Empty string when unavailable. |
| address | string | Registered company address as returned by VIES. Empty string when unavailable. |
| requestDate | string | Date of the VIES query (YYYY-MM-DD+offset). |
| timestamp | string | ISO 8601 timestamp of when the validation was performed. |
All responses return HTTP 200. When an error occurs, the response body contains an error field. Check for this before reading validation results.
| Error code | Description |
|---|---|
invalid_api_key | Missing or invalid API key. Pass your key in the x-api-key header. |
vies_unavailable | VIES is temporarily down. retryable: true is included — implement exponential backoff. |
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:
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.
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.
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 →
Validate VAT numbers — with consultation numbers — directly inside Claude Desktop, Cursor, or any MCP-compatible AI client. Published on npm as vies-mcp.
Tools: validate_vat (validity + company data + consultation number) and vies_status (live per-country VIES availability). Source: github.com/acirema792/vies-mcp.
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).
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.