---
title: "Validate an EU VAT ID"
method: GET
path: "/v1/vat/{vatId}"
tags: ["VAT validation"]
---

# Validate an EU VAT ID

`GET /v1/vat/{vatId}`

## Request

- Base URL: `https://api.vatnode.dev`
- URL: `https://api.vatnode.dev/v1/vat/{vatId}`
- Auth: HTTP bearer

Validates the supplied VAT ID against VIES, falling back to the
relevant national registry when VIES is unavailable. Without a
requester, for some member states vatnode also queries the national
VAT register at the same time as VIES, and the register answer is
returned if it arrives first – `source` is then the register code and
`consultationNumber` is `null`. Results for the base validation are cached for up to 15
minutes.

Configure a requester VAT once in the dashboard (Account details, or
`PATCH /v1/me/requester`) to obtain a VIES `consultationNumber`
on every call automatically. When the account has a requester
configured, the cache is bypassed so a fresh consultation number is
always issued.

## Path parameters

- `vatId` string, required

## Response `200`

Validation result.

- VatValidationResult
  - `valid` boolean, required: Whether the VAT ID is valid. With `source: VIES` this is the VIES verdict. With a national registry `source` it is that register’s answer about domestic VAT registration, not a VIES confirmation that the number is valid for intra-EU transactions – re-check in VIES before relying on it to zero-rate an intra-EU supply.
  - `vatId` string, required: Normalised VAT ID (uppercase, no separators).
  - `countryCode` string, required: Two-letter country code extracted from the VAT ID.
  - `countryName` string, required
  - `companyName` string, nullable, required
  - `companyAddress` string, nullable, required
  - `companyRegistrationDate` string, date, nullable, required
  - `companyForm` string, nullable, required
  - `industryDescription` string, nullable, required
  - `registryCode` string, nullable, required: The company’s number in the national business register, in its national format (e.g. `0112038-9` for a Finnish Y-tunnus, `123 456 789` for a French SIREN). Read off the VAT number where the VAT number is built from it (BE, BG, CZ, DK, FI, FR, SE) and taken from the national register for LT. `null` everywhere else, and for VAT numbers built from a personal number (a Czech rodné číslo, a Swedish personnummer), and for a Bulgarian 10-digit suffix.
  - `registryCodeName` string, nullable, required: Local name of `registryCode` in the country’s first official language (e.g. `Y-tunnus`, `numéro SIREN`). `null` when `registryCode` is `null`.
  - `taxId` string, nullable, required: The national tax number the VAT number carries, in its national format – e.g. the Spanish NIF, the Polish NIP, the Greek ΑΦΜ, or `CZ` + IČO for a Czech DIČ. The same value as `registryCode` where one number serves both (BE, DK, FI, FR, SE). `null` where the VAT number is not the national tax number.
  - `taxIdName` string, nullable, required: Local name of `taxId` in the country’s first official language (e.g. `NIP`, `ΑΦΜ`). `null` when `taxId` is `null`.
  - `commercialName` string, nullable, required: Trade / commercial name where the source provides one distinct from the legal `companyName`. `null` when the source has only one name or no commercial name (never a duplicate of `companyName`).
  - `companyStatus` string, nullable, required: Best-effort normalized operational status from the source registry (one of `active`, `inactive`, `ceased`, `bankrupt`, `liquidation`, `dissolved`, or a lowercased source value that does not map cleanly). Enrichment metadata only – it never overrides `valid`. `null` when the source provides no status.
  - `secondaryActivities` string[], required: Secondary activity / classification descriptions where the source provides them (the main activity is `industryDescription`). Empty array when none or unavailable.
  - `companyAgeYears` integer, nullable, required: Full years between `companyRegistrationDate` and `verifiedAt` (floored). `null` when `companyRegistrationDate` is `null`.
  - `registryPrivacy` boolean, required: `true` when the source national register marks the record as restricted from publication at the registrant’s own request – French ‘non-diffusible’, Dutch *afscherming*. The record above is still returned in full; the flag tells you the registrant asked their register not to hand these details out, which matters if you plan to republish them. vatnode’s own public /check pages mask a flagged record. `false` for every other result, including countries whose register exposes no such flag.
  - `website` string, nullable, required: Company homepage as the national business register publishes it, lower-cased and without a trailing slash, as the register has it – it may be written without a scheme (`www.example.fi`). `null` when the register publishes none or the number is not enriched from a register that carries one. Always present.
  - `countryVat` CountryVatInfo, required
    - `vatName` string, required
    - `vatAbbr` string, nullable, required
    - `currency` string, required
    - `standardRate` number, required
    - `reducedRates` number[], required
    - `superReducedRate` number, nullable, required
    - `parkingRate` number, nullable, required
    - `vatNumberFormat` string, nullable, required
    - `vatNumberPattern` string, nullable, required: Regular expression the VAT number should match.
    - `identifiers` CountryIdentifiers, required: Names, never numbers, of the country’s company registrar, company register, register number, business tax number and VAT identification number.
      - `registryAuthorityName` LocalizedName, nullable, required: A name keyed by ISO 639-1 language code – every official language of the country, plus `en`. `null` where no official name could be confirmed.
        - `en` string, required
      - `registryName` LocalizedName, nullable, required: A name keyed by ISO 639-1 language code – every official language of the country, plus `en`. `null` where no official name could be confirmed.
        - `en` string, required
      - `registryCodeName` LocalizedName, nullable, required: A name keyed by ISO 639-1 language code – every official language of the country, plus `en`. `null` where no official name could be confirmed.
        - `en` string, required
      - `taxIdName` LocalizedName, nullable, required: A name keyed by ISO 639-1 language code – every official language of the country, plus `en`. `null` where no official name could be confirmed.
        - `en` string, required
      - `vatIdName` LocalizedName, nullable, required: A name keyed by ISO 639-1 language code – every official language of the country, plus `en`. `null` where no official name could be confirmed.
        - `en` string, required
    - `countryVatUpdatedAt` string, required: Date the rate dataset was last updated (ISO 8601).
  - `checkId` string, uuid, required: UUIDv7 identifier for this validation, and the primary key of the stored check record. It is issued only after that record is committed, so a `checkId` you hold always names a check vatnode can still produce – it is a receipt, not a request id. If the record cannot be stored, the response is `AUDIT_WRITE_FAILED` (HTTP 502) with no `checkId` and no quota consumed.
  - `verifiedAt` string, date-time, required
  - `source` 'VIES' | 'CACHE' | 'BZST' | 'MF_PL' | 'ANAF_RO' | 'ARES_CZ' | 'SIREN_FR' | 'PRH_FI' | 'CVR_DK' | 'BOLAGSVERKET_SE' | 'KVK_NL' | 'CBE_BE' | 'JARS_LV' | 'JARS_LT' | 'AJPES_SI', required: Which system produced this result. - `VIES` — the EU Commission’s VIES service answered directly. The only source that can carry a `consultationNumber`. - `CACHE` — the base validation was served from vatnode’s cache (a prior VIES or national-register result, up to 15 minutes old). A cached result does not say which of the two produced it. Never carries a consultation number. - A national registry code (`MF_PL` for PL, `ANAF_RO` for RO, `ARES_CZ` for CZ) – vatnode answered from that national register instead of VIES, either because VIES was unavailable for the country or, for some member states (currently CZ), because the register answered before VIES. `valid` then reflects the national register (domestic VAT registration), not a VIES confirmation that the number is valid for intra-EU transactions. Only possible when no requester was supplied; never carries a consultation number. The other national codes in the enum are not returned as a validity source. A successful requester-authenticated call (one returning a `consultationNumber`) always has `source: VIES`, because national fallback is disabled whenever a requester is supplied.
  - `consultationNumber` string, nullable, required: VIES `requestIdentifier`, returned only when the account has a requester VAT configured (dashboard Account details) and VIES answered successfully via `checkVatApprox`. `null` when no requester is configured, when the answer came from a national register, or when served from cache.
  - `specialTerritory` SpecialTerritory, required: An EU special-VAT territory whose treatment diverges from its member state’s – the Canary Islands (IGIC, not VAT), the French overseas departments, Åland, Madeira and the Azores among them. **This is inferred from the address, not a tax determination.** No special territory has its own VIES prefix: a Canary Islands business carries an ordinary `ES` number and an Åland business an ordinary `FI` one, so the only signal is a postal code in the trader address that falls in a range exclusive to the territory. It reflects the registered address, never the place of supply that governs any given transaction.
    - `code` 'canary-islands' | 'ceuta' | 'melilla' | 'guadeloupe' | 'martinique' | 'french-guiana' | 'reunion' | 'mayotte' | 'aland-islands' | 'madeira' | 'azores' | 'busingen' | 'helgoland' | 'livigno' | 'campione-ditalia' | 'mount-athos', required: Stable machine-readable territory identifier.
    - `name` string, required: Human-readable territory name.
    - `memberState` string, required: Parent member state’s VIES country prefix.
    - `euVatArea` boolean, required: `false` — outside the EU VAT area, under its own regime (Canary IGIC) or behind a fiscal border (Åland). `true` – inside the EU VAT area but on regional rates (Madeira, Azores).
    - `source` 'ADDRESS_INFERRED', required: Provenance. Always `ADDRESS_INFERRED` – the value exists only because a postal code was read out of the trader address.

## Other responses

- `400`: The VAT ID is not a valid VAT number format (`INVALID_FORMAT`). In test mode, a VAT ID not starting with `XX` also returns `INVALID_FORMAT`.
- `401`: Missing or invalid API key.
- `403`: VIES reported the VAT ID or your IP as blocked (`VAT_BLOCKED` / `IP_BLOCKED`). Surfaced as `VIES_ERROR`.
- `422`: The account’s configured requester VAT (dashboard setting) is invalid in VIES. Only returned when a requester is configured. Fix or clear it to continue.
- `429`: Monthly quota exceeded.
- `500`: Unhandled internal server error.
- `502`: VIES returned an unexpected protocol error. Also returned when a requester is configured and VIES answered `valid: true` without a consultation number (retried once first) – the check is withheld rather than delivered without its audit evidence, and no quota is consumed. `AUDIT_WRITE_FAILED` is the third case: the check itself succeeded, but its record could not be stored, so the verdict and its `checkId` are withheld rather than handed back unrecorded. No quota is consumed and the check is safe to retry.
- `503`: VIES is unavailable. Without a requester, vatnode also exhausted national-registry fallbacks. With a requester, national fallback is intentionally skipped.
- `504`: VIES request timed out and no fallback was available.

---

[API](https://skmtc.dev/vatnode/apis/vatnode-api.md) · [All operations](https://skmtc.dev/vatnode/apis/vatnode-api/llms.txt) · [OpenAPI document](https://skmtc.dev/vatnode/apis/vatnode-api/revisions/c65828db2037?raw)
