Verify ID
The verification of an ID is the core operation of VerifyVAT.
You provide an entity ID and specify, or let the system infer, what kind of ID it is. Our engine then validates the ID syntactically, checks it against one or more official registries, and merges the available evidence into a normalised representation of the entity behind it.
If you are using an official SDK, see Verify and decide to learn how to perform a verification and derive decision-grade signals from the result using advanced reasoning helpers.
Note: The
/verifyendpoint is the exact same engine used by our public lookup form on verifyvat.com. The UI wraps the API response with formatting and visual aids, but the underlying evidence, registry queries, fallback rules, issues, and outcomes are identical. Using the API gives you the same quality and reliability as the web interface, just programmatically.
How verification works
Verification follows a predictable, four-step process. Each step contributes evidence that is preserved and exposed in the response.
1. Interpret the ID
VerifyVAT first resolves the ID type. This can happen in three ways:
- an explicit
typeis provided, - the type is inferred from a supplied
country, - or full inference is performed using
type: "auto".
The resolved type determines which validation rules and registries are applicable.
2. Validate syntax
The ID is checked against structural rules: format, length, and checksum where applicable.
This step produces the syntax.valid flag. It is purely syntactic and completely independent of registry availability or responses. A structurally invalid ID cannot exist in its current form, regardless of registry coverage.
3. Query registries
Our engine queries the registries associated with the resolved ID type.
If "expand": true (default), linked IDs discovered during verification (for example VAT → business register → LEI) are also queried in their respective registries. Each registry interaction is recorded independently.
4. Merge and normalise data
Registry responses are merged following the principles described in Cross-registry checks and normalised according to Data normalisation.
Raw registry values are preserved for traceability and auditing. Normalised fields are provided to support comparison, storage, and downstream processing.
Making a request
The endpoint accepts GET and POST requests.
Parameters may be provided via path segments, query parameters, or JSON body fields.
### JSON body (recommended):POST https://api.verifyvat.com/v1/verifyContent-Type: application/json{ ### Option A: explicit type "type": "{type}", "id": "{id}",
### Option B: infer type from country "country": "{country}", "id": "{id}",
### Option C: full inference "type": "auto", "id": "{id}"
### Optional flags (default: true) "lookup": true, "expand": true}
### Path segments:POST https://api.verifyvat.com/v1/verify/:type/:idContent-Type: application/json{ ### Optional flags (default: true) "lookup": true, "expand": true}
### Query parameters:GET https://api.verifyvat.com/v1/verify?type={type}&id={id}
### Mixed:GET https://api.verifyvat.com/v1/verify/:type?id={id}Parameters
| Parameter | Required | Description |
|---|---|---|
id | yes | Raw identifier string. |
type | no | ID type (e.g. no_vat, tw_ubn, ww_lei, ...) or auto for full inference. |
country | no | ISO 3166-1 alpha-2 country code to restrict national patterns. |
lookup | no | Whether to query registries (default: true). |
expand | no | Whether to follow linked IDs (default: true). |
Understanding the response
The /verify response uses the common envelope described in Response envelope. All verification semantics are contained in data.process and data.entity.
It is designed to answer three practical questions:
- What did the engine do with the supplied ID?
- What do registries (and caches) say about it?
- What does that imply about the underlying entity, and how should you act on it?
1. The verification process
process describes how the engine handled your request, what evidence it observed along the way, and what is the outcome of the verification.
1.1 Input
| Field | Description | Optional |
|---|---|---|
value | Normalized ID value used for processing. | No |
type | Resolved ID type (e.g. no_vat, no_orgnr, tw_ubn). Derived from input, country, or type: "auto". | No |
display | Canonical formatted representation of the ID, suitable for display and UX. | No |
These fields let you reconcile user input with what the engine actually processed, especially when inference is involved.
1.2 Per-registry evidence
Each registry consulted produces an entry in process.sources. This is where data quality and fallback behaviour become visible.
| Field | Description | Optional |
|---|---|---|
id | Internal registry identifier ( no-brreg, tw-gcis, ww-gleif, …). | No |
coverage | full or partial coverage for this ID type in that registry. | No |
outcome | Registry-specific result: confirmed, unconfirmed, or unknown. | No |
origin | registry, fresh-cache, or stale-cache. | No |
registryStatus | responsive, unreachable, skipped, or error. | No |
observedAt | ISO 8601 timestamp for when the data was observed at the registry. | No |
Use this section to distinguish fresh data from fallback data and to detect degraded conditions. See Caching and stale data for a detailed discussion of how to interpret freshness signals and fallback behaviour.
1.3 Syntax, outcome, and issues
process.output summarises what the engine concluded after validation and registry checks.
| Field | Description | Optional |
|---|---|---|
syntax.valid | true if the ID passes structural rules (pattern, length, checksum), false otherwise. | No |
syntax.method | syntactic for full checksum validation, simple when only lightweight checks are available. | No |
outcome | Overall verification outcome: confirmed, unconfirmed, or unknown. | No |
origin | Where the final outcome comes from: registry, fresh-cache, stale-cache, or none. | No |
coverage | Combined coverage for this ID type: full, partial, or none. | No |
issues | Diagnostic flags such as syntax-invalid, no-registry, registry-unreachable, registry-error, partial-coverage, stale-only. | No |
outcome should always be interpreted together with issues.
Issues might include:
| Issue | Meaning |
|---|---|
syntax-invalid | The ID is structurally invalid and cannot exist in its current form. |
no-registry | There is no backing registry for this ID type, so no confirmation is possible. |
registry-unreachable | The registry could not be reached during this verification attempt. This is a transient condition that may resolve on retry. |
registry-error | An error occurred during registry querying. Check process.sources[] for details. |
partial-coverage | The ID type is only partially covered by available registries, so lack of confirmation is not definitive. |
stale-only | The result is based entirely on fallback cache data, with no fresh registry confirmation. This should be treated accordingly. |
An outcome of confirmed means that at least one registry (or its cache) positively matched the ID. Outcomes of unconfirmed or unknown indicate lack of evidence, not always proof of non-existence.
2. The entity representation
If at least one registry or inference step can say something meaningful about the subject behind the ID, entity contains a normalised view of that organisation or individual.
If nothing can be said beyond syntax and registry outcome, entity is null.
entityis not strictly tied tooutput.outcome === "confirmed".
Some IDs encode information even when no registry confirms existence.
keyvalues are ephemeral transient strings for cross-referencing within the response.
2.1 Identity
identity groups the entity’s core identifying material into consistent collections.
| Field | Description | Optional |
|---|---|---|
identity.identifiers | Array of all known IDs for this entity. | No |
identity.registrations | Array of registrations tying this entity to official schemes. | No |
identity.statusRecords | Array of status records describing the entity lifecycle. | No |
identity.legalForm | Normalised legal form with ELF codes and localised labels. | Yes |
identity.formationCountry | Formation country. | Yes |
2.2 Identifiers
identifiers[] are the set of ID values known to refer to the same entity.
Use this array as the primary source of stable values for linking and reconciliation.
| Field | Description | Optional |
|---|---|---|
identifiers[*].key | Internal ID key - unique within the response and used for cross-referencing. | No |
identifiers[*].type | ID type (e.g. no_orgnr, tw_ubn, ww_lei, ...). | No |
identifiers[*].id | ID value. | No |
identifiers[*].issueCountry | Country of issuance. | Yes |
identifiers[*].presentation | UI-oriented formatting metadata. | Yes |
2.3 Registrations
registrations[] describe participation in official schemes and who operates them.
| Field | Description | Optional |
|---|---|---|
registrations[*].key | Internal registration key - unique within the response and used for cross-referencing. | No |
registrations[*].kind | Registration kind ( identity, tax, activity, compliance, filing, trade, or other). | No |
registrations[*].scheme | Scheme name (e.g. vat, orgnr, lei, ...). | No |
registrations[*].authority | Authority operating the scheme ( government, regulator, industry-body, or data-vendor). | No |
registrations[*].jurisdiction | Jurisdiction country or economic area (e.g. NO, EU, WW, ...). | No |
registrations[*].status | Registration status ( active, suspended, ended, or unknown). | No |
registrations[*].since / until | Optional temporal bounds. | Yes |
registrations[*].identifiers | ID keys associated with this registration. | No |
Multiple registrations may refer to the same ID.
2.4 Status records
statusRecords[] represent operational or legal states as reported by registries.
| Field | Description | Optional |
|---|---|---|
statusRecords[*].key | Internal status record key - unique within the response and used for cross-referencing. | No |
statusRecords[*].value | Raw status value from the registry. | Yes |
statusRecords[*].localizedValue | Localised, human-readable status value from the registry. | Yes |
statusRecords[*].language | Language code (e.g. en, no, zh-CN, ...). | Yes |
statusRecords[*].code | Normalised status code ( active, dormant, restricted, ended, or unknown). | No |
statusRecords[*].qualifiers | Qualifier codes (e.g. bankrupt, liquidating, struck-off, ...). | No |
statusRecords[*].since / until | Optional temporal bounds. | Yes |
2.5 Names
names[] are current and historical names reported by registries.
| Field | Description | Optional |
|---|---|---|
names[*].key | Internal name key - unique within the response and used for cross-referencing. | No |
names[*].value | Name string. | No |
names[*].kind | Name type ( legal, trading, transliterated, short, or other). | No |
names[*].language | Language code (e.g. en, no, zh-CN, ...). | Yes |
names[*].script | Script code. | Yes |
names[*].since / until | Optional validity period. | Yes |
2.6 Addresses
addresses[] represent registry-provided address material in both raw and normalised forms.
| Field | Description | Optional |
|---|---|---|
addresses[*].key | Internal address key - unique within the response and used for cross-referencing. | No |
addresses[*].kind | Address type ( legal, headquarters, mailing, billing, residential, or other). | No |
addresses[*].value | Raw address string from the registry. | Yes |
addresses[*].normalized | Normalised address forms. | No (fields inside may be null) |
addresses[*].components | Parsed address components. | No (components may be null) |
addresses[*].geo | Best-effort geolocation. | No (coordinates may be null) |
addresses[*].since / until | Optional validity period. | Yes |
For details on parsing and normalisation, see Data normalisation.
2.7 Timeline
timeline[] is the ordered set of notable lifecycle and record events associated with the entity. These can be either directly observed in registry data or inferred by the engine based on patterns and changes.
| Field | Description | Optional |
|---|---|---|
timeline[*].key | Internal event key - unique within the response and used for cross-referencing. | No |
timeline[*].domain | High-level area of the entity this event refers to ( existence, registration, name, address, meta, or other). | No |
timeline[*].kind | Normalised event kind, notably establishment, cessation, registration-addition, name-change, address-update, record-update, etc. | No |
timeline[*].date | Event date. | No |
timeline[*].ref | Key reference to the primary subject of this event. | Yes |
timeline[*].inferred | true if this event was inferred/derived by the engine. | Yes |
timeline[*].note | Optional human-readable note for UIs / debugging. | Yes |
timeline[*].data | Structured contextual data (e.g. from / to snapshots, registry-specific payload). | Yes |
3. Making decisions with /verify
In practice, verification decisions should be anchored on output.outcome and output.issues[], with sources[] used to assess evidence quality when necessary.
A few common patterns:
- IDs with
syntax-invalidcannot exist in their current form. - A
confirmedoutcome withoutstale-onlyindicates registry-backed confirmation. partial-coverageandno-registryindicate degraded evidence rather than definitive non-existence.stale-onlymeans only fallback cache data was available and should be treated with caution.
Real-world examples
The example below shows a successful verification of a Norwegian VAT number.
This example shows a structurally invalid ID, which fails syntax validation before any registry checks are performed.