Btw-nummer controleren in België via VIES: stap voor stap
Btw-nummer controleren België: formaatcontrole, VIES, het resultaat lezen, bewijs bewaren en omgaan met downtime. Met curl- en JavaScript-voorbeelden.
Lever je goederen aan een Belgisch bedrijf of krijg je een factuur van een Belgische leverancier, dan wil je weten of het btw-nummer in orde is. Een fout of ongeldig nummer kan betekenen dat je ten onrechte btw-vrij factureert, of dat je btw niet kunt aftrekken. De controle zelf is snel, maar de details tellen: wat zegt het antwoord wel en niet, en wat bewaar je erna? Hier doorloop je het proces stap voor stap.
Stap 1: controleer het formaat
Een Belgisch btw-nummer bestaat uit BE en 10 cijfers, bijvoorbeeld BE0821015819 (voorbeeld). Oudere nummers hadden 9 cijfers; daar komt een voorloopnul bij. De laatste twee cijfers vormen een controlegetal: 97 min de rest van de deling van de eerste acht cijfers door 97.
Die controle doe je lokaal, zonder netwerkaanroep. Ze kost niets en vangt typfouten op voor je VIES lastigvalt. Op onze gratis btw-controle-tool zie je de checksum meteen.
function normalizeBelgianVat(input) {
let digits = String(input).toUpperCase().replace(/^BE/, "").replace(/\D/g, "");
if (digits.length === 9) digits = "0" + digits;
if (!/^[01]\d{9}$/.test(digits)) return null;
const base = Number(digits.slice(0, 8));
const check = Number(digits.slice(8));
if (97 - (base % 97) !== check) return null;
return `BE${digits}`;
}
Stap 2: leid het btw-nummer af
Heb je alleen het ondernemingsnummer, dan is het btw-nummer BE plus die 10 cijfers. Maar let op: dat is een kandidaat, geen zekerheid. Niet elke onderneming is btw-plichtig. Sommige vzw’s, vrije beroepen en eenmanszaken onder de franchiseregeling hebben een ondernemingsnummer zonder actief btw-nummer. Het verschil tussen de nummers staat in het verschil tussen ondernemingsnummer en btw-nummer, maar de regel is eenvoudig: afleiden mag, bevestigen moet.
Stap 3: vraag VIES
VIES is de dienst van de Europese Commissie die zegt of een nummer op dit moment geregistreerd is voor intra-Europese btw. Voor België krijg je meestal ook de naam en het adres terug. Via de KVKBase API vraag je het zo op:
curl -s "https://api.kvkbase.nl/v1/be/validate/vat/BE0821015819" \
-H "Authorization: Bearer YOUR_API_KEY"
Het antwoord bevat vatNumber, valid, name, address, validatedAt en status. Een controle kost 1 token. Je mag het nummer in elke schrijfwijze meesturen.
Stap 4: lees het resultaat juist
| Veld | Betekenis |
|---|---|
valid | true als het nummer nu geregistreerd is voor intra-Europese btw |
name, address | wat VIES teruggeeft, vergelijk dit met je klant of leverancier |
validatedAt | het tijdstip van de controle, het anker van je bewijs |
status | de uitkomst van de controle, bewaar ze mee |
Vergelijk altijd de naam uit het antwoord met de naam op je factuur of in je klantendossier. Een geldig nummer van een ander bedrijf is nog altijd een probleem.
Wat VIES wel en niet zegt
VIES zegt: dit nummer is op dit moment geregistreerd voor intra-Europese btw. Dat is alles. Het zegt niet:
- dat het bedrijf solvabel is of zijn rekeningen betaalt
- dat de tegenpartij is wie ze beweert te zijn
- dat de naam overeenkomt met jouw klant
- dat het nummer geldig was op een datum in het verleden
Voor die vragen heb je meer nodig. Kijk bij een Belgische klant of leverancier controleren hoe je een btw-controle aanvult met een profiel van de onderneming.
Intra-Europese leveringen: controleren en bewijzen
Lever je goederen aan een btw-plichtige in een andere EU-lidstaat, dan factureer je die in principe zonder btw. Voorwaarde is dat de afnemer een geldig btw-nummer heeft. Controleer het nummer dus voor de levering en bewaar het bewijs. Als de fiscus later vraagt waarom je geen btw rekende, toon je het resultaat met datum en tijd.
De precieze voorwaarden hangen af van je situatie en van de btw-regels in jouw land, dus vraag advies aan je boekhouder. Maar de gewoonte is altijd dezelfde: controleer vooraf, noteer het resultaat en bewaar het zolang je factuur bewaard moet blijven.
Stap 5: sla het bewijs op
Bewaar bij elke controle het nummer, het resultaat, de naam en het adres uit het antwoord, en het tijdstip. Dat laatste veld, validatedAt, is wat je later nodig hebt. Overschrijf een oud resultaat niet: voeg een nieuwe rij toe.
CREATE TABLE vat_check (
id BIGSERIAL PRIMARY KEY,
vat_number VARCHAR(12) NOT NULL,
valid BOOLEAN,
status TEXT,
name TEXT,
address TEXT,
validated_at TIMESTAMP NOT NULL
);
Stap 6: ga om met VIES-downtime
VIES draait op de systemen van de lidstaten en is soms niet bereikbaar of beperkt het aantal aanvragen per lidstaat. Dat is normaal en heeft niets met jouw nummer te maken. Behandel zo’n uitval als onbekend, niet als ongeldig. Via de API krijg je dan een UPSTREAM_ERROR (HTTP 502) of UPSTREAM_BUDGET (HTTP 503), en bij te veel aanvragen een 429. Probeer later opnieuw met een groeiende wachttijd.
const API_KEY = process.env.KVKBASE_API_KEY;
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
async function checkBelgianVat(vat, retries = 3) {
const url = `https://api.kvkbase.nl/v1/be/validate/vat/${encodeURIComponent(vat)}`;
for (let attempt = 0; attempt <= retries; attempt++) {
const res = await fetch(url, { headers: { Authorization: `Bearer ${API_KEY}` } });
if (res.ok) return res.json();
const retryable = [429, 502, 503].includes(res.status);
if (!retryable || attempt === retries) {
throw new Error(`VAT check failed with status ${res.status}`);
}
await sleep(2000 * 2 ** attempt); // 2s, 4s, 8s
}
}
const result = await checkBelgianVat("BE0821015819");
console.log(result.valid, result.name, result.validatedAt);
Een misvormd nummer wordt al afgewezen voor er een controle plaatsvindt (HTTP 400, INVALID_CBE_NUMBER) en kost daarom niets. Blijft VIES lang onbereikbaar, laat de levering dan niet blindelings doorgaan: noteer dat je de controle probeerde en herhaal ze zodra het kan.
Volume en kosten
Heb je een lijst klanten om na te lopen? Haal dan per onderneming het profiel op via POST /v1/be/lookup/batch (max. 25 nummers per aanroep). Het resultaat bevat per nummer ook het vat-blok. Elke controle en elk item in een batch kost 1 token. Een gratis account geeft je 50 tokens per maand, zonder kredietkaart. Voor meer volume bekijk je de prijzen. Alle velden en foutcodes staan in de API-referentie, en een overzicht van de Belgische mogelijkheden vind je op de België-pagina. Zoek je eerst het nummer van een bedrijf? Lees dan ondernemingsnummer opzoeken.