Documentation
A REST API over the Belgian Crossroads Bank for Enterprises. JSON in, JSON out.
Authentication
Send your key in the X-API-Key header on every request.
curl -H "X-API-Key: your_key" https://companydata.nalios.be/api/v1/companies/0214596464
Endpoints
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/companies/{number} | One company. Params: lang, establishments, vies |
| GET | /api/v1/companies/{number}/history | Change history of one company |
| GET | /api/v1/companies | Search. Params: name, nace, city, zip, legal_form, status, limit |
| GET | /api/v1/autocomplete | Type-ahead by name or number. Param: q |
| GET | /api/v1/changes | Everything changed since a datetime. Param: since |
| GET | /api/v1/companies/{number}/accounts | Filed annual accounts, computed ratios (solvency, liquidity, return on equity), directors/shareholders, and companies linked through the same directors or shareholders (related_companies). Param: limit, refresh |
| GET | /api/v1/companies/{number}/benchmark | Percentile and sector quartiles for each ratio, compared against peers. Param: depth (NACE prefix length) |
| GET | /api/v1/companies/{number}/group | Ownership around a company: who holds it (owners) and what it holds (subsidiaries), with percentages and the controlling owner. Param: depth (1 to 3 levels each way) |
| GET | /api/v1/people/{person_id}/mandates | Every company a director, representative or shareholder is linked to |
| GET | /api/v1/people/{person_id}/network | Multi-hop director/shareholder graph, up to 3 hops. Param: depth |
| GET | /api/v1/watchlist | List the companies watched by your key |
| POST | /api/v1/watchlist | Add a company to your watchlist. Body: {"enterprise_number": "..."} |
| DELETE | /api/v1/watchlist/{number} | Remove a company from your watchlist |
| PUT | /api/v1/webhook | Set the URL notified when a watched company changes. Body: {"url": "https://..."} |
| GET | /health | Service status, no key required |
Known limitations
These are real gaps, not bugs — worth knowing before you build on them:
- No revenue figure for small companies. Belgian law does not require the abridged accounting scheme (most SMEs) to disclose turnover.
revenueand any ratio derived from it are only present for companies filing under the full scheme. - A benchmark can silently widen its comparison group. Each ratio is first compared within companies of the same size band; if too few peers exist in that band, it falls back to the whole sector. The response always says which via
compared_against— check it before treating a percentile as apples-to-apples. - Some companies file their accounts as a PDF only. A deposit whose model code ends in
-pis a PDF model: the National Bank publishes no structured data for it. We read the key figures (balance sheet, income statement, staff) from the PDF itself and keep them only when the balance sheet balances to the euro. Such deposits are flaggedpdf_only: true, and theirsourceispdfonce figures were read. Directors (name, function and dates of each mandate) and shareholders (name, nature of the rights and share of the voting rights) are read from their lists in the filing when these follow a known layout, never with a private street address, and a PDF that cannot be read reliably is returned without figures. - Percentages are fractions.
percentageon shareholders and participations is a share between 0 and 1 (0.6444means 64.44 %). - The ownership tree only knows what is on file.
/groupis built from filed accounts we hold; a level that is missing means its accounts are not on record yet, not that nobody owns the company. - Year-on-year figures come from the filing itself. Growth rates compare the current exercise with the previous-year column of the same filing, and are
nullwhen that column is absent. Revenue-based ratios (margins, revenue per FTE) only exist for the full scheme. - Bankruptcy status is not verified.
legal.bankruptisnullandlegal.checkedisfalsefor every company: uselegal.situationinstead, taken from the legal situation recorded in the BCE/KBO (bankruptcy, judicial reorganisation, liquidation). Never treat a missingbankruptas a confirmed "not bankrupt".
Languages
All coded values carry both the raw code and a readable label. Pass lang=FR or lang=NL to choose the label language; Dutch is used as a fallback when a translation is missing.
Errors
| Status | Meaning |
|---|---|
| 401 | missing api_key or invalid api_key |
| 404 | Unknown enterprise number |
| 429 | quota exceeded or rate limit exceeded |
Machine-readable
OpenAPI specification · Postman collection · Interactive reference
Client libraries
Minimal clients you can drop into your project: Python · JavaScript
Removed companies
A company that exercised its right to erasure is removed from every endpoint and returns 404. The /api/v1/changes feed still emits a minimal entry with "suppressed": true so you can purge your own cache.