Tax Number Validation
Tax Number Validation lets you verify that a tax number (VAT number, company registration, GST number, etc.) is properly formatted and, where supported, actively registered with the tax authority. Clearvo handles the API calls to VIES, HMRC, and 10+ national registries, normalises the number, and caches results to avoid redundant calls.
Key capabilities
- Format validation for 100+ countries
- Real-time authority checks for 37 jurisdictions (EU VIES, UK HMRC, NO, AU, FR, DK, BR, JP, TW, PE)
- Normalisation and typo alternatives (O→0, missing country prefix, cross-country swap)
- Result caching (30-day TTL for valid VAT, 14-day national, 7-day invalid)
- Batch validation up to 20 per call
https://api.clearvo.io/v1) and the same csk_live_* / csk_test_* API key system. No separate credentials are needed — the same key you use for e-invoicing works here.Authentication
All Tax Number Validation endpoints use the same x-api-key header as the rest of the Clearvo API. Pass your live or test key on every request.
x-api-key: csk_live_...
Use csk_test_* keys for sandbox — authority calls are skipped in sandbox mode and the response reflects the format result only, with sandbox: true. See the Sandbox section for full details.
Validate a Tax Number
Validates a single tax number. Performs a format check and, if the format is valid and checkAuthority is not set to false, calls the relevant authority registry to confirm the number is actively registered.
Endpoint
POST https://api.clearvo.io/v1/tax-numbers/validate
curl https://api.clearvo.io/v1/tax-numbers/validate \
-X POST \
-H "x-api-key: csk_live_..." \
-H "Content-Type: application/json" \
-d '{
"countryCode": "DE",
"taxNumber": "DE123456789",
"registryType": "auto",
"checkAuthority": true,
"force": false
}'
Request body fields
| Field | Type | Required | Description |
|---|---|---|---|
| countryCode | string | Yes | ISO 3166-1 alpha-2 country code. Use EL for Greece, XI for Northern Ireland. |
| taxNumber | string | Yes | The tax number to validate. Can include or omit the country prefix — Clearvo normalises it before checking. |
| registryType | "auto" | "vat" | "national" | No | Default: "auto". "auto" first tries the VAT register, then falls back to the national company register. "vat" checks the VAT register only. "national" checks the national company register only. |
| checkAuthority | boolean | No | Default: true. Whether to call the tax authority after a valid format check. Set to false for format-only validation. |
| force | boolean | No | Default: false. Bypass the cache and always call the authority live. |
Successful response
{
"countryCode": "DE",
"taxNumber": "DE123456789",
"normalized": "DE123456789",
"registryType": "vat",
"format": {
"valid": true
},
"authority": {
"checked": true,
"valid": true,
"name": "Example GmbH",
"address": "Musterstraße 1, 10115 Berlin",
"requestId": "abc-123"
},
"alternatives": [],
"cached": false,
"sandbox": false,
"checkedAt": "2026-06-20T09:00:00.000Z"
}
Error response — invalid format
When format validation fails, the API still returns HTTP 200. The format.valid field is false, the authority is not checked, and any auto-generated alternative matches are returned in the alternatives array.
{
"countryCode": "DE",
"taxNumber": "INVALID",
"normalized": "INVALID",
"registryType": "vat",
"format": {
"valid": false,
"error": "DE VAT numbers must match pattern DE + 9 digits"
},
"authority": {
"checked": false
},
"alternatives": [
{
"taxNumber": "DE123456789",
"countryCode": "DE",
"reason": "Added missing DE prefix",
"format": { "valid": true },
"authority": { "checked": true, "valid": true, "name": "Example GmbH" }
}
],
"cached": false,
"sandbox": false,
"checkedAt": "2026-06-20T09:00:00.000Z"
}
Response Reference
Full field reference for the validation response object returned by both the single and batch endpoints.
| Field | Type | Description |
|---|---|---|
| format.valid | boolean | true if the tax number passes format validation for the given country. |
| format.error | string | Present when format.valid is false — human-readable description of why the format failed. |
| authority.checked | boolean | true if an authority API was called (or a cache hit exists for a prior authority check). |
| authority.valid | boolean | null | true if the authority confirmed the number is actively registered. null if the authority was not checked. |
| authority.name | string | Business name returned by the authority. Not all registries return this field. |
| authority.address | string | Registered address returned by the authority. Not all registries return this field. |
| authority.requestId | string | VIES consultation ID (EU VIES only). Required for audit trails in some EU jurisdictions — store this alongside the validation result. |
| alternatives | array | Array of alternative match objects when the original number failed format validation. Each entry includes its own format and authority result. See Alternative Matches. |
| cached | boolean | true if the authority result came from the cache; false if a live authority call was made on this request. |
| sandbox | boolean | true when the request was made with a test key. Authority calls are skipped in sandbox mode. |
| checkedAt | string | ISO 8601 timestamp of when the validation was performed (or when the cached result was originally obtained). |
Batch Validation
Validate up to 20 tax numbers in a single request. Each item in the batch is processed independently — a format error or authority timeout on one item does not affect the others.
Endpoint
POST https://api.clearvo.io/v1/tax-numbers/validate-batch
curl https://api.clearvo.io/v1/tax-numbers/validate-batch \
-X POST \
-H "x-api-key: csk_live_..." \
-H "Content-Type: application/json" \
-d '{
"items": [
{ "countryCode": "DE", "taxNumber": "DE123456789" },
{ "countryCode": "GB", "taxNumber": "GB123456789" },
{ "countryCode": "FR", "taxNumber": "FR12345678901" }
]
}'
{
"results": [
{
"index": 0,
"countryCode": "DE",
"taxNumber": "DE123456789",
"format": { "valid": true },
"authority": { "checked": true, "valid": true, "name": "Example GmbH" }
},
{
"index": 1,
"countryCode": "GB",
"taxNumber": "GB123456789",
"format": { "valid": true },
"authority": { "checked": true, "valid": true, "name": "Example Ltd" }
},
{
"index": 2,
"error": "Invalid country code"
}
],
"total": 3,
"valid": 2,
"invalid": 0,
"errors": 1,
"sandbox": false
}
Each result includes an index matching the original position in the items array. Items that cannot be processed (malformed input, unknown country code) appear with an error string and no validation fields. The top-level valid, invalid, and errors counts let you quickly triage the batch without iterating every result.
Lookup History
Retrieve a paginated history of all validation lookups made under your API key. Useful for auditing, reconciliation, and tracking which supplier or customer tax numbers have been verified.
Endpoint
GET https://api.clearvo.io/v1/tax-numbers/lookups
curl "https://api.clearvo.io/v1/tax-numbers/lookups?page=1&limit=20&country=DE&valid=true" \
-H "x-api-key: csk_live_..."
Query parameters
| Parameter | Type | Description |
|---|---|---|
| page | integer | Page number. Default: 1. |
| limit | integer | Results per page. Default: 20, max: 100. |
| country | string | Filter to a specific ISO 3166-1 alpha-2 country code. |
| valid | boolean | Filter by authority validity. true returns only confirmed-valid lookups. false returns only failed lookups. |
{
"data": [ /* validation result objects */ ],
"page": 1,
"limit": 20,
"total": 142,
"stats": {
"totalChecks": 142,
"validCount": 128,
"invalidCount": 14,
"authorityCheckedCount": 130,
"countriesChecked": 12
}
}
The stats object reflects counts across your full lookup history (not just the current page), making it useful for dashboard-style summary displays without requiring a separate aggregation call.
Country Coverage
Live authority checks
The following 37 jurisdictions support real-time authority lookups. When checkAuthority: true (the default), Clearvo calls the relevant registry and returns the live registration status.
| Country | Registry | Authority | Notes |
|---|---|---|---|
| AT — Austria | VAT | EU VIES | |
| BE — Belgium | VAT | EU VIES | |
| BG — Bulgaria | VAT | EU VIES | |
| BR — Brazil | National | BrasilAPI CNPJ | Company registration (CNPJ). Returns business name and status. |
| CY — Cyprus | VAT | EU VIES | |
| CZ — Czech Republic | VAT | EU VIES | |
| DE — Germany | VAT | EU VIES | |
| DK — Denmark | National | CVR API | Returns company name and CVR registration status. |
| EE — Estonia | VAT | EU VIES | |
| EL — Greece | VAT | EU VIES | Use country code EL (not GR) for VIES lookups. |
| ES — Spain | VAT | EU VIES | |
| FI — Finland | VAT | EU VIES | |
| FR — France | VAT + National | EU VIES + SIREN API | VAT via VIES; national company register via SIREN API. |
| GB — United Kingdom | VAT | HMRC VAT API | Post-Brexit — uses HMRC directly, not VIES. |
| HR — Croatia | VAT | EU VIES | |
| HU — Hungary | VAT | EU VIES | |
| IE — Ireland | VAT | EU VIES | |
| IT — Italy | VAT | EU VIES | |
| JP — Japan | VAT | NTA Qualified Invoice Registry | Returns registration status for Qualified Invoice issuers (T-number). |
| LT — Lithuania | VAT | EU VIES | |
| LU — Luxembourg | VAT | EU VIES | |
| LV — Latvia | VAT | EU VIES | |
| MT — Malta | VAT | EU VIES | |
| NL — Netherlands | VAT | EU VIES | |
| NO — Norway | National | Brreg (Brønnøysund) | Returns company name and organisation number status. |
| PE — Peru | National | SUNAT | Best-effort free tier. May experience higher latency during peak hours. |
| PL — Poland | VAT | EU VIES | |
| PT — Portugal | VAT | EU VIES | |
| RO — Romania | VAT | EU VIES | |
| SE — Sweden | VAT | EU VIES | |
| SI — Slovenia | VAT | EU VIES | |
| SK — Slovakia | VAT | EU VIES | |
| TW — Taiwan | National | GCIS (Ministry of Economic Affairs) | Returns business name and registration status. |
| XI — Northern Ireland | VAT | EU VIES | Use country code XI for Northern Ireland VAT numbers post-Brexit. |
| AU — Australia | National | ABN Lookup | Activating soon Free registration required — contact support to enable for your account. |
Format validation only
An additional 80+ countries are supported for format validation — the tax number is checked against the known pattern for that country but no authority registry is called. This covers all major economies not listed above, including:
Americas: AR, CA, CL, CO, MX, UY, VE · Asia-Pacific: CN, HK, ID, IN, KR, MY, NZ, PH, SG, TH, VN · Middle East & Africa: AE, EG, IL, KE, MA, NG, SA, ZA · Europe (non-EU): CH, IS, LI, MD, MK, RS, TR, UA · Other: all remaining ISO 3166-1 countries with a known tax number format.
checkAuthority: false to skip the authority step entirely — the response is faster and the format result is still returned. This is also the recommended approach when you only need to validate a number before sending an invoice, and are not building a supplier onboarding or KYC flow.Alternative Matches
When a tax number fails format validation, Clearvo automatically generates a set of candidate corrections and validates each one. Alternatives that pass format validation are then checked against the authority (subject to checkAuthority and force settings). All results appear in the alternatives array on the main response.
This is especially useful in supplier onboarding flows where users frequently make the same input mistakes. Rather than returning a hard failure and asking the user to correct it, your application can present the most likely alternative.
Correction types
Common OCR and manual entry typos are corrected before re-validating. The most common substitutions are O→0 (letter O entered instead of zero) and I→1 (letter I entered instead of one). Clearvo generates corrected candidates and checks each one.
If the number you pass has no country prefix (e.g. you send 123456789 for Germany), Clearvo tries prepending the expected prefix (DE123456789) and re-validates. The reason field on the alternative will be "Added missing DE prefix".
Some country pairs share similar VAT number formats, and users occasionally enter the wrong country code. Clearvo automatically checks common neighbouring-country swaps: ES↔PT, AT↔DE, SE↔NO, BE↔NL. If the number validates under the swapped country and the authority confirms it, the alternative is returned with "reason": "Matched as PT VAT number" (for example).
Each alternative object in the array includes the full taxNumber, countryCode, reason, format, and authority fields — identical in structure to the top-level response, so you can present it to the user or use it programmatically without additional lookups.
Caching
Clearvo caches validation results per (country code, normalised tax number, registry type) tuple. Cached results are returned instead of making a live authority call, unless force: true is passed. The cached field on the response tells you whether a live call was made.
Cache TTLs
| Result type | TTL | Rationale |
|---|---|---|
| Valid VAT number | 30 days | VAT registrations are stable — deregistrations are uncommon and typically take time to propagate. |
| Valid national number | 14 days | National registries update more frequently; shorter TTL balances freshness with call volume. |
| Invalid number | 7 days | The number may be corrected and re-submitted by a supplier — short TTL ensures a fresh check soon. |
| Authority error (timeout / service unavailable) | Not cached | Transient errors are never cached — the next request will always attempt a live call. |
force: true to bypass the cache when you need a guaranteed live authority check — for example, immediately before issuing an invoice, or when a supplier has informed you their VAT number was recently reinstated. Forced calls count against your authority API quota.Sandbox
Use a csk_test_* API key to make sandbox requests. Sandbox mode is identical to production except that authority calls are skipped — no requests are made to VIES, HMRC, or any other registry. Format validation runs normally.
Sandbox responses always include "sandbox": true. The authority.checked field will be false and authority.valid will be null for all sandbox requests, regardless of whether the format is valid.
curl https://api.clearvo.io/v1/tax-numbers/validate \
-X POST \
-H "x-api-key: csk_test_..." \
-H "Content-Type: application/json" \
-d '{ "countryCode": "DE", "taxNumber": "DE123456789" }'
{
"countryCode": "DE",
"taxNumber": "DE123456789",
"normalized": "DE123456789",
"registryType": "vat",
"format": { "valid": true },
"authority": {
"checked": false
},
"alternatives": [],
"cached": false,
"sandbox": true,
"checkedAt": "2026-06-20T09:00:00.000Z"
}