API v2: Reference Data, VAT validation and real-time webhooks
Company Belgium API v2 adds Reference Data endpoints (NACE, legal forms), Belgian VAT validation, payment risk scoring and HMAC-signed webhooks.
In brief
Company Belgium API v2 introduces four structural additions: Reference Data endpoints for NACE codes and legal forms (designed for client-side caching), real-time Belgian VAT number validation, a 0-100 payment risk score, and HMAC-SHA256-signed webhooks to receive BCE events in push mode rather than polling. v1 stays supported through end of 2026.
Why v2?
Our v1 BCE API delivered on its promise: expose Belgian company data and Company Belgium enrichments cleanly. But usage taught us two things: integrators want push over polling, and they want stable reference tables rather than a pile of codes to translate on every call.
v2 runs in parallel with v1 and introduces four structural additions: Reference Data, VAT validation, risk scoring, and webhooks.
Reference Data
NACE codes, legal forms, activity groups are now accessible via dedicated endpoints:
GET /api/v2/reference/nace-codes?lang=en
GET /api/v2/reference/juridical-forms?lang=en
GET /api/v2/reference/activity-groups?lang=en
These tables rarely change. They're meant to be cached client-side (ETag + 24h Cache-Control provided).
1 2 3 4 5
class="code-comment">// Load NACE codes once at startup, cache in memory
const res = await fetch(class="code-string">"https:class="code-comment">//companybelgium.be/api/v2/reference/nace-codes?lang=en", {
headers: { class="code-string">"X-API-Key": key, class="code-string">"X-API-Secret": secret }
});
const naceCodes = await res.json();
Belgian VAT validation
Highly requested endpoint:
1 2 3 4
curl -X POST https://companybelgium.be/api/v2/vat/validate \
-H "X-API-Key: pk_live_..." \
-H "X-API-Secret: sk_live_..." \
-d '{"vatNumber": "BE 0200.065.765"}'
Returns the normalized version, the status (valid / invalid / bad_format) and the matched BCE enterprise number. This same mechanism powers our Belgian invoicing module with automatic intracom reverse-charge.
Payment risk scoring
1 2 3
curl https://companybelgium.be/api/v2/companies/0200065765/payment-risk \
-H "X-API-Key: pk_live_..." \
-H "X-API-Secret: sk_live_..."
Returns a 0–100 score and a category (low / moderate / high / critical), built from aggregated signals.
Real-time webhooks
The most structural addition. Subscribe to events:
company.updated
company.status_changed
company.filing_deposited
establishment.created
establishment.closed
Each event fires a POST to your URL, signed with HMAC SHA-256 using a shared secret. Header X-Espero-Signature.
1 2 3 4 5 6 7 8 9
import crypto from class="code-string">"crypto";
function verify(rawBody: string, signature: string, secret: string) {
const expected = crypto
.createHmac(class="code-string">"sha256", secret)
.update(rawBody)
.digest(class="code-string">"hex");
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
}
Exponential retry up to 24 h, admin page to manually replay an event on consumer-side failure. For a complete guide on webhooks and their security, read our article on webhooks and real-time notifications.
Authentication and quotas
Auth still uses a public key + secret pair, unchanged since v1. Quotas are more generous on v2.
Migrating from v1
v1 stays supported through end of 2026. For most cases: replace /api/ with /api/v2/ in your URLs. A detailed migration guide is coming next sprint. In the meantime, consult the REST endpoints reference guide for the full v2 route structure.
Frequently asked questions
What is the difference between Company Belgium BCE API v1 and v2 ?
v1 covers Belgian company identity: BCE number, name, address, NACE, status. v2 adds four extra layers: Reference Data endpoints for NACE codes and legal forms with 24-hour client-side caching, real-time Belgian VAT number validation, a 0-100 payment risk score, and HMAC-SHA256-signed webhooks. Both versions run in parallel and share the same authentication mechanism.
How does Belgian VAT number validation work via the v2 API ?
Send a POST request to /api/v2/vat/validate with the VAT number to check. The endpoint normalizes the format, verifies the Belgian structure and returns the status valid, invalid or bad_format along with the matched BCE enterprise number. As long as the number is not valid, the invoice stays in draft in the Company Belgium invoicing module.
What are Reference Data in the v2 API and why cache them ?
Reference Data are three stable reference tables: NACE codes with FR/NL/EN descriptions, legal forms and activity groups. They are accessible via dedicated endpoints with a 24-hour Cache-Control header and an ETag. The idea is to load these tables once at application startup and keep them in memory rather than requesting a code description on every company lookup.
How do I secure incoming BCE webhooks sent by the v2 API ?
Each webhook fires a POST to your URL with an X-Espero-Signature header containing an HMAC-SHA256 of the body computed with your shared secret. On the receiver side, recompute the HMAC of the raw received body and compare it with the header signature using crypto.timingSafeEqual to prevent timing attacks. An exponential retry up to 24 hours ensures delivery in case of temporary unavailability of your endpoint.
Comments
Related articles

What's new at Company Belgium: purchase invoice upload, VAT declaration pre-calculation
Two big time savers in invoicing this month: bulk-upload your supplier invoices with automatic extraction of accounting data, and get the Intervat boxes pre-filled from your sales and purchase invoices.

Multi-tenant and white-label: embed the BCE API at your clients
Company Belgium now offers a multi-tenant mode with per-client custom landing, header and branding. Ideal for franchises, accounting networks and API resellers.

Peppol via Dokapi: automatic send and ingest of B2B invoices
Our Dokapi integration sends your invoices in UBL format over the Peppol network and auto-ingests inbound invoices as purchase invoices.
