The evidence model
Claims, sources, observation time, freshness, and what an outcome does not say.
A VAT.tools result is not a fact about the world. It is a claim: one scoped assertion about a legal entity, an establishment, a VAT registration, or a relationship, together with typed evidence that supports it. This page explains the vocabulary the API encodes.
What a claim is
A response can carry several claims at once — that an entity is active, that a particular VAT identifier is valid, that an entity and a registration are related. Each claim has its own outcome and its own references into the evidence list. Two claims can disagree without the response being broken; the product surfaces that as conflicting rather than picking a winner.
Outcome vocabulary
Outcomes are typed, and only some of them are conclusions. The distinction is the reason this API exists in this shape.
| Field | Type | Description |
|---|---|---|
valid | authority | The authority reported the registration as valid at the recorded time. |
invalid | authority | The authority explicitly reported the identifier as not valid. Only this outcome may block under a configured policy. |
source_unavailable | no answer | The authority or path could not answer. Retry later or route to review; never render as invalid. |
unsupported | no coverage | The operation or jurisdiction is outside supported coverage for this source. Show “not available here”. |
not_found | scoped absence | No result in the queried source population. It is scoped to that source, not a statement about the entity. |
conflicting | disagreement | Eligible evidence sources materially disagree. Each observation stays visible until a claim policy resolves it. |
The evidence record
Every claim points at evidence. The evidence record is the provenance an integration must preserve when it stores or displays a result.
| Field | Type | Description |
|---|---|---|
sourcerequired | object | The authority or registry that produced the observation, with an optional URL. |
capabilityrequired | string | The capability the source answered for, such as vat_validation or company_verification. |
authorityScope | string | null | The jurisdiction or scope the source's answer covers. |
observedAtrequired | datetime | When the source recorded the fact. This time never changes when the same evidence is served again. |
retrievedAt / servedAtrequired | datetime | When VAT.tools retrieved the evidence and when it delivered it. Delivery time is not observation time. |
deliveryFormrequired | enum | live_source_call, official_snapshot, cached_observation, coalesced_observation, or sandbox_fixture. |
completion | object | Whether the source answered completely, and the boundary it answered within. |
Who ran what, in which environment, and whether this response is a replay of an earlier one.
"operation": { "id": "0f6c2a90-1b3e-4c5d-9a7f-2e4b6c8d0a12", "kind": "vat_validation", "status": "completed", "environment": "sandbox", "createdAt": "2026-09-14T09:12:04.118Z", "completedAt": "2026-09-14T09:12:04.481Z", "replayed": false }
The operation's own answer. Only an authority outcome says valid or invalid; unsupported and source_unavailable never do.
"result": { "kind": "vat_validation", "outcome": "valid", "vatRegistration": { "countryCode": "DE", "vatNumber": "123456789" }, "legalName": null, "checkedAt": "2026-09-14T09:12:04.470Z", "cached": false, "evidenceRefs": ["ev-1"] }
Scoped assertions and the links between entities and registrations. Each one keeps the evidence that supports it.
"claims": [], "relationships": [ { "type": "vat_registration_of", "outcome": "confirmed", "vatRegistration": { "countryCode": "DE", "vatNumber": "123456789" }, "evidenceRefs": ["ev-1"] } ], "conflicts": [], "issues": []
The source leaves its fingerprint: who answered, when it was observed, and how it was delivered.
"evidence": [ { "id": "ev-1", "source": { "name": "Bundeszentralamt für Steuern", "url": null }, "capability": "vat_validation", "environment": "sandbox", "authorityScope": "EU", "observedAt": "2026-09-14T09:12:04.470Z", "retrievedAt": "2026-09-14T09:12:04.481Z", "servedAt": "2026-09-14T09:12:04.481Z", "deliveryForm": "sandbox_fixture", "completion": { "state": "complete", "boundary": "authority" } } ]
How long this answer stays current, plus the source's own cadence — which a faster delivery cannot change.
"freshness": { "effectiveMaxAgeSeconds": 86400, "satisfied": true, "sourceCadenceSeconds": 21600, "limitation": "Authority cadence is unchanged by this delivery." }
What the call consumed and how it settled. A replay settles at zero.
"usage": { "meter": "vat_validation", "unitsCharged": 1, "settlementReason": "completed" }
Freshness and cached evidence
Freshness is a property of the evidence, not of when you asked. A response reports the source's own cadence and the window within which the answer is considered current. Serving a stored result again produces cached evidence: same observation time, a new delivery time, and an explicit label.
Do not refresh observedAt
A later retrieval of an earlier observation is not a new observation. If you display a cached result, show its original observation time and say that it is cached.
When the window closes
Past the effective window, or when the caller requires fresher evidence, the correct behaviour is to re-check. Live-only operations such as company resolution always re-check; a cache can never answer a resolution.
Association is not validity
Reverse VAT discovery returns two different things that are easy to conflate: a VAT association — a sourced link between a legal entity and a registration — and, separately, the validity of that registration from an authority. An entity can be associated with a registration whose current status you have not checked, and a valid identifier does not by itself prove any company claim.