VIES Consultation Number: What It Is and How to Store It
25 May 2026 · 8 min read

When you validate an EU VAT number through VIES, the response can include a reference string called the consultation number. Most developers ignore it because the SOAP response is verbose and the field name is unfamiliar. It is also the most portable piece of evidence a finance team can extract from the VIES response — the timestamp, validated VAT ID, returned trader name and address, and your own request logs all matter too, but the consultation number is the one that VIES itself attests to. Here is what it is, how to extract it, and how to store it.
What the consultation number actually is
The consultation number is a server-generated reference that VIES attaches to a validation result when the request includes a requester VAT number. It identifies a specific lookup — VAT ID X validated by requester Y on date Z — and is intended as evidence that the validation took place.
In SOAP terms, when you call the VIES checkVatApprox operation and pass requesterCountryCode and requesterVatNumber, the response includes a requestIdentifier field. That string is the consultation number. A plain checkVat call without requester fields will not return one — VIES only issues a consultation number when there is a requester to attribute the lookup to.
The European Commission describes this on the VIES FAQ and the "Check a VAT number (VIES)" guidance: the requester-qualified validation produces a reference that the requester can keep as proof of due diligence. The underlying legal frame for intra-EU supplies is in Council Directive 2006/112/EC (the EU VAT Directive) — it sets out the conditions under which a supply can be treated as VAT-exempt or under reverse charge, and validating the buyer's VAT registration is one of the substantive requirements national authorities draw on.
It is not a tax document on its own and it does not "certify" the VAT number in any legal sense — it is an audit trail entry that ties a moment of validation to two parties.
The consultation number only exists for requester-qualified lookups. If your code path calls VIES without supplying the requester VAT ID, you will get a valid/invalid answer but no reference to keep.
Why finance teams care about it
Intra-EU B2B supplies under the reverse-charge mechanism shift VAT liability to the buyer when the buyer is a taxable person registered for VAT in another member state. The seller does not charge VAT. To do this lawfully, the seller has to be able to show that they took reasonable steps to verify the buyer's VAT registration at the time of the supply.
What "reasonable steps" means varies by member state, but in practice the bar most finance and audit teams aim for is:
- A timestamped record that the VAT ID was checked against VIES
- The result of that check
- Ideally, a reference issued by VIES itself tying the check to the requester
The consultation number is the third item. Without it, you have your own logs saying you called VIES. With it, you have an externally generated reference that VIES itself issued and that can support audit evidence on intra-EU supplies. A public reverse-lookup workflow for auditors does not exist as a documented feature — what the consultation number provides is a server-issued identifier tied to a specific lookup, which is generally treated as more credible than self-produced log lines. Auditors may request this kind of evidence during a VAT audit; it is not always required, but it is among the strongest pieces of proof available from the validation pipeline itself.
How to extract it from a raw VIES SOAP call
If you are calling VIES directly, you need to build a SOAP envelope with the requester fields populated. The response will include requestIdentifier as a sibling of countryCode, vatNumber, and the trader name/address fields:
async function checkVatWithConsultation(opts: {
countryCode: string
vatNumber: string
requesterCountryCode: string
requesterVatNumber: string
}) {
const envelope = `<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:urn="urn:ec.europa.eu:taxud:vies:services:checkVat:types">
<soapenv:Body>
<urn:checkVatApprox>
<urn:countryCode>${opts.countryCode}</urn:countryCode>
<urn:vatNumber>${opts.vatNumber}</urn:vatNumber>
<urn:requesterCountryCode>${opts.requesterCountryCode}</urn:requesterCountryCode>
<urn:requesterVatNumber>${opts.requesterVatNumber}</urn:requesterVatNumber>
</urn:checkVatApprox>
</soapenv:Body>
</soapenv:Envelope>`
const res = await fetch(
'https://ec.europa.eu/taxation_customs/vies/services/checkVatService',
{
method: 'POST',
headers: { 'Content-Type': 'text/xml; charset=utf-8' },
body: envelope,
}
)
const xml = await res.text()
// Parse with your XML library of choice; the field is:
// <requestIdentifier>WAPIAAAAX9999999</requestIdentifier>
return parseViesResponse(xml)
}
The field is a string of roughly 16 characters starting with letters (the exact format is not contractual — treat it as opaque). Do not parse it; do not assume a length. Store it as text.
Two things commonly trip teams up the first time they implement this:
checkVatvscheckVatApprox. The plaincheckVatoperation does not accept requester fields and does not return a consultation number. You needcheckVatApproxeven if you do not care about the "approximate match" features it adds — that is the operation that supports requester-qualified lookups.- The requester must be a valid EU VAT ID. VIES validates the requester pair before issuing a consultation number. If your company is not VAT-registered in the EU, you cannot produce one directly through VIES — only through a service that holds an EU VAT ID and acts on your behalf.
How to store it
Treat the consultation number as part of the validation record, not a separate concept. A reasonable schema for a vat_checks table:
CREATE TABLE vat_checks (
id UUID PRIMARY KEY,
vat_id TEXT NOT NULL, -- cleaned, e.g. DE123456789
country_code TEXT NOT NULL,
valid BOOLEAN NOT NULL,
source TEXT NOT NULL, -- 'VIES' | national fallback
consultation_number TEXT, -- VIES requestIdentifier, nullable
requester_vat_id TEXT, -- the VAT ID you used as requester
trader_name TEXT,
trader_address TEXT,
checked_at TIMESTAMPTZ NOT NULL,
customer_id UUID -- whatever ties this to your domain
);
CREATE INDEX vat_checks_vat_id_checked_at_idx
ON vat_checks (vat_id, checked_at DESC);
A few rules that hold up in practice:
- Never overwrite an old check with a new one. Append a new row. The consultation number is timestamp-specific evidence; overwriting it destroys the audit trail.
- Persist the requester VAT ID alongside it. A consultation number on its own is meaningless without knowing who the requester was.
- Allow the column to be null. Lookups that come from a national fallback (BZSt for DE, INSEE for FR, KBO for BE, and so on — tax authority and company registry APIs more broadly) do not produce a VIES
requestIdentifier. You still want those rows in the table; they just have a differentsourceand no consultation number. - Index on
(vat_id, checked_at DESC). The audit query you will actually run is "show me the most recent VIES-sourced check for this VAT ID before the invoice date" — that index makes it cheap.
A note on evidence quality across sources: a national-registry validation is not equivalent to a VIES validation for audit purposes. National sources return different fields, normalise data differently, and reflect a different legal status — a BZSt confirmation, for example, is a yes/no signal from the German tax authority and does not produce a VIES requestIdentifier. Treat source as part of the evidence: persist it immutably alongside the row, never overwrite it on a subsequent VIES success, and when exporting for audit, expose the original source so the reviewer can weigh the evidence accordingly.
What to surface in your UI
Most teams do not expose the consultation number to end customers. It is internal evidence. Two places where it does show up:
- Invoice PDFs — some teams print "VAT verified — VIES ref: WAPIAAAAX…" near the customer VAT ID, mostly as a signal of due diligence to the buyer's finance team. This is a convention, not a requirement.
- Audit export — when an auditor asks for evidence of validation on intra-EU supplies, a CSV with columns
invoice_id, vat_id, consultation_number, checked_at, requester_vat_id, sourceis what they want. Build the export once and it is reusable for every audit.
What it does not do
Three claims you will sometimes see about the consultation number that are worth flagging as overstated:
- It does not "certify" the VAT number. VIES is a routing layer over national databases. The consultation number is evidence that you asked and what answer VIES returned. It does not transfer liability if the answer was wrong because a national database was stale.
- It does not replace your own logs. If your VIES client times out or returns a transport error, you will not have a consultation number for that attempt — but you should still log the attempt. Your own logs and the consultation number are complementary, not alternatives.
- It is not a tax invoice field. No EU member state's invoicing rules require the consultation number to appear on the invoice itself. Putting it there is a convention some teams adopt; it is not in the § 14 UStG / equivalent invoice content lists.
How vatnode surfaces it
vatnode runs a requester-qualified VIES call on every live validation and returns the consultation number as a top-level field in the response:
const res = await fetch(
'https://api.vatnode.dev/v1/vat/DE123456789',
{ headers: { Authorization: `Bearer ${process.env.VATNODE_API_KEY}` } }
)
const data = await res.json()
// {
// "valid": true,
// "countryCode": "DE",
// "vatNumber": "123456789",
// "name": "Example GmbH",
// "address": "Musterstr. 1, ...",
// "source": "VIES",
// "consultationNumber": "WAPIAAAAX9999999",
// "checkedAt": "2026-05-25T08:30:00.000Z"
// }
If source is VIES, consultationNumber is populated. If the call fell back to a national source — see the VIES downtime guide for when that happens, and the German VAT number guide for the BZSt case specifically — consultationNumber is null and source reflects the actual database that answered. The field is the same requestIdentifier string VIES would have returned from a direct SOAP call; store it as-is.
Get the consultation number on every validation
vatnode runs requester-qualified VIES calls by default and returns the consultation number as a structured field — no SOAP parsing on your side. Free plan, 100 requests/month.