Response format
Every field in the success, error, and batch response envelopes.
Every response from the vatverify API uses the same outer envelope: a data or error object, always accompanied by a meta block.
Success envelope
{
"data": {
"valid": true,
"vat_number": "IE6388047V",
"country": {
"code": "IE",
"name": "Ireland",
"vat": {
"name": "Value Added Tax",
"abbreviation": "VAT",
"currency": "EUR",
"standard_rate": 23,
"reduced_rates": [9, 13.5],
"super_reduced_rate": 4.8,
"parking_rate": 13.5,
"number_format": "IE + 7 digits + 1-2 letters",
"number_pattern": "^IE\\d{7}[A-Z]{1,2}$",
"updated_at": "2026-04-01"
}
},
"company": {
"name": "GOOGLE IRELAND LIMITED",
"address": "3RD FLOOR, GORDON HOUSE, BARROW STREET, DUBLIN 4"
},
"verify_id": "WAPIAAAAZ2Re-K4H",
"verified_at": "2026-04-15T14:11:49.110Z"
},
"meta": {
"request_id": "019d917e-4fa4-766e-9e0f-d977b47bf2c6",
"latency_ms": 2310,
"cached": false,
"source": "vies",
"source_status": "live"
}
}data fields
| Field | Type | Description |
|---|---|---|
data.valid | boolean | true if the VAT number is registered and active with the registry. false if not registered. |
data.vat_number | string | Normalized form of the input: uppercase, no spaces or punctuation. |
data.country | object | Country metadata: code, name, and a vat object with rates and format info (see below). |
data.company | object | null | name and address from the registry. null when the registry withholds data (e.g. Germany withholds company details by policy). |
data.verify_id | string | null | Official consultation identifier from the registry (VIES consultation number or HMRC reference). Populated only when requester_vat_number is provided and the source supports it. null for CH, LI, and NO lookups. Tax auditors accept this as proof of verification. |
data.verified_at | string | ISO 8601 timestamp of the original registry fetch. Unchanged on cache hits, always reflects when the data was actually retrieved. |
meta fields
| Field | Type | Description |
|---|---|---|
meta.request_id | string | UUID for this request. Include it when contacting support. |
meta.latency_ms | number | Server-side processing time in milliseconds. ~2ms on cache hits, 500–3000ms on live registry calls. |
meta.cached | boolean | true if this result was served from cache. Cache hits don't count toward your monthly quota. |
meta.source | string | Which registry answered: vies, hmrc, bfs, or brreg. |
meta.source_status | string | live: fresh from the registry. cached: served from cache. degraded: registry was unavailable and we fell back to a cached result. |
Error envelope
{
"error": {
"code": "rate_limited",
"message": "Monthly quota of 500 exceeded."
},
"meta": {
"request_id": "a1b2c3d4-...",
"latency_ms": 0
}
}| Field | Type | Description |
|---|---|---|
error.code | string | Machine-readable error code. See Error reference. |
error.message | string | Human-readable description. Safe to log; do not display directly to end users. |
meta.request_id | string | UUID for the failed request. |
meta.latency_ms | number | Always 0 for auth and format errors (rejected before processing). |
Response headers
Every response includes:
| Header | Description |
|---|---|
X-RateLimit-Limit | Your plan's monthly quota. |
X-RateLimit-Remaining | Calls remaining this month. |
X-RateLimit-Reset | Unix timestamp when quota resets (00:00 UTC on the 1st of next month). |
X-Request-Id | Same UUID as meta.request_id. Useful for logging before parsing the body. |
On 429 responses, a Retry-After header is also included (seconds until reset).
Batch envelope
Batch responses wrap per-item results in a summary:
{
"data": {
"summary": {
"total": 3,
"successful": 2,
"failed": 1
},
"results": [
{ "ok": true, "data": { "..." : "..." } },
{ "ok": false, "error": { "code": "registry_unavailable", "message": "..." } },
{ "ok": true, "data": { "..." : "..." } }
]
},
"meta": { "..." : "..." }
}Each item in results is a discriminated union on ok:
ok: true→datacontains a full validation result (same shape as the single validate responsedatafield)ok: false→errorcontainscodeandmessagefor that item only
Per-item errors (invalid_format, country_unsupported, registry_unavailable) do not fail the whole batch. Auth, plan, and rate-limit errors fail the whole request before any items are processed.
See POST /v1/validate/batch for the full endpoint reference.