CompanyBelgium

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.

April 19, 20268 min read

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).

TypeScript
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:

Terminal
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

Terminal
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.

TypeScript
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.

Ready to get started?

Create your free account and get your API keys in minutes.

Comments

Loading comments…

Leave a comment

Not published — used only to notify you.

Comments are moderated before publication.

Related articles