Developers
Belgian company data your software can read: identity and status from the KBO/BCE register, the verified act timeline extracted from the Belgisch Staatsblad / Moniteur belge, officers with currency semantics, and parsed NBB annual accounts. Two surfaces over the same corpus, one API key for both: a JSON REST API for conventional clients, and a Model Context Protocol endpoint for AI agents.
This reference is English only, on purpose: every identifier, tool name and error string in the surface below is English. The product itself is Dutch, French and English.
Every fact we serve carries the identifier of the document it came from, so your users can check it and your agent can cite it:
- Act-derived facts carry
numac, the Belgian gazette publication number, plus the publication date. - Mandates carry the numac and publication date of the act that established them.
- Register facts (name, legal form, seat, status, NACE) come from the KBO/BCE open data.
- Financial figures are the lines as filed with the National Bank; ratios are derived from them and labelled as derived.
The other half of the promise is admitting what is missing. Deep act
extraction does not cover the whole corpus yet, so the MCP surface
exposes get_extraction_status: it tells you
how many gazette acts are on file for a company and how many have been
extracted, so an empty timeline is explainable rather than mysterious.
Sector-inapplicable financial ratios come back as an explicit
not-applicable marker with a reason, never as a misleading number.
| REST base URL | https://checked.be/api/v1 |
| MCP endpoint | https://checked.be/mcp |
| Authentication | X-Api-Key request header, on both surfaces |
| Format | JSON. REST fields are snake_case; MCP tool results are camelCase (the two serializers differ, this is not a typo) |
| Methods | Read-only. Every documented endpoint is a GET; MCP is JSON-RPC over POST but exposes no write tool |
| Rate limit | 60 requests per minute (see the rate-limit section, the two surfaces count differently) |
| CORS | Not enabled. Call from your server, not from a browser |
| Caching | Every /api/v1 response carries Cache-Control: public, max-age=300 |
| OpenAPI | None published. This page is the specification |
| Versioning | In the path (/v1/). Additive changes ship without a version bump; see the changelog |
Send your key in the X-Api-Key header. There is
no bearer-token form and no query-string form. Keys are issued by hand
today: mail enterprise@checked.be
and say what you are building. There is no self-service key page yet,
and this reference will not pretend otherwise.
curl -sS -H "X-Api-Key: $CHECKED_API_KEY" \ https://checked.be/api/v1/companies/0400378485
The gate is fail-closed: if no keys are provisioned on the server, every
call gets 401, including calls that carry a key.
Four endpoints. The {kbo} path segment accepts any
form whose digits end in a 10-digit enterprise number:
0400378485, 0400.378.485 and
BE0400378485 all resolve to the same company.
The dossier spine: identity, seat, risk band, insolvency rollup and the
mandate list. risk is never null (an unscored
company gets band Unknown with score 0);
rollup and address are null
when we hold nothing. band is PascalCase and one of
Unknown, Low,
Moderate, Elevated,
High, Severe.
{
"enterprise_number": "0400378485",
"legal_name": "COLRUYT GROUP",
"legal_form": "610",
"primary_nace": "47110",
"status": "active",
"address": { "street": "...", "zip": "1500", "city": "Halle" },
"risk": {
"band": "Low", "score_out_of100": 88, "probability": 0.0121,
"altman_z": 3.42, "model_version": "...", "evaluated_at": "2026-07-30T02:11:04+00:00"
},
"rollup": null,
"insolvency_event_count": 0,
"admin_event_count": 4,
"mandates": [
{ "role": "...", "role_kind": "...", "name": "...", "address": null,
"from": "2019-05-14", "to": null, "source": "...", "source_numac": "2019..." }
]
}
A bare JSON array of legal-lifecycle events, no envelope.
source is one of
faillissement, reorg,
insolvency_interim, kbo_admin;
severity is low,
med or high. Not paginated:
you get the whole timeline.
[
{ "source": "faillissement", "severity": "high", "numac": "2026...",
"pub_date": "2026-05-20", "event_kind": "...", "court": "...",
"event_date": "2026-05-14", "detail": "..." }
]
The compact insolvency aggregate on its own, for cheap screening of a
portfolio. Returns 404 when the company exists but
has no rollup on file.
{
"total_events": 3, "interim_signals": 1, "reorg_events": 1,
"faillissement_events": 1, "first_signal_date": "2026-01-05",
"last_signal_date": "2026-05-20", "has_open_faillissement": true
}
Company lookup by name, enterprise number, VAT number or NACE code.
limit defaults to 20 and is clamped to 1..50. A blank
or missing q returns [] with
status 200, not an error. Not paginated and no total count: this is a
resolver, not a corpus dump. match_kind tells you
which lane matched (name, address,
kbo, nace). On this endpoint
kind is always company and
href/subtitle are always null;
they exist so the shape matches the internal omni-search wire format.
curl -sS -H "X-Api-Key: $CHECKED_API_KEY" \
'https://checked.be/api/v1/search?q=colruyt&limit=5'
[
{ "enterprise_number": "0400378485", "legal_name": "COLRUYT GROUP",
"slug": "colruyt-group-0400378485", "city": "Halle", "primary_nace": "47110",
"match_kind": "name", "matched_address": null, "kind": "company",
"href": null, "subtitle": null }
]
Every error carries a JSON body with a single error
string. Match on the status code, not on the wording.
| 401 | {"error":"Missing X-Api-Key header."} |
| 401 | {"error":"Invalid API key."} |
| 401 | {"error":"API access is not enabled."} |
| 404 | {"error":"Unknown enterprise number."} |
| 429 | {"error":"Rate limit exceeded: ..."} plus Retry-After: 60 |
REST /api/v1/* | 60 requests per minute, counted per client IP, fixed window |
MCP /mcp | 60 requests per minute, counted per API key when a key is present, otherwise per IP |
| Over the limit | 429 with Retry-After: 60 |
| Repeated bad keys | More than 20 failed /mcp authentications in a minute from one IP get 429 instead of 401 |
One caveat worth knowing before you build a batch job: the REST budget
is per IP and is shared with the unauthenticated
/internal/search and
/health/status endpoints. If you need sustained
throughput, higher limits are a mail away rather than something to work
around.
https://checked.be/mcp speaks MCP over streamable
HTTP: JSON-RPC 2.0 on POST, an event stream on
GET, session id in the
Mcp-Session-Id header. Protocol versions
2024-11-05 through 2025-11-25
are negotiated at initialize. Server identity is
Checked.be version 1.0.0.
The legacy HTTP+SSE transport is disabled, so that one path is the
entire surface: there are no separate stream or message endpoints to
configure. Six tools, no resources, no prompts, nothing that writes.
The endpoint requires the same X-Api-Key header as
the REST API. A client configuration without it will fail at
initialize with a 401.
{
"mcpServers": {
"checked": {
"type": "http",
"url": "https://checked.be/mcp",
"headers": { "X-Api-Key": "your-key" }
}
}
}
Key name and nesting differ per client (some use
servers rather than
mcpServers); the URL, the transport type and the
header are what matter.
| search_companies query, page |
Resolve a name, enterprise number, VAT number or NACE code to companies. Ten hits per page, each with its canonical dossier URL. Start here, then feed enterprise_number to the other tools. |
| get_company_profile kbo |
Identity, status, seat, NACE, headline figures from the latest filed annual accounts, financial-health score and bankruptcy-probability band. Banks, insurers and holdings get explicit not-applicable fields instead of misread trading ratios. |
| get_company_acts kbo, limit |
The differentiator: the verified, per-act extracted gazette timeline. Typed facts with resolved actor names and amounts, every fact stamped with its numac. Newest first, 1 to 100 acts. |
| get_company_officers kbo |
Board and mandates with currency semantics: current, stale (open per the register but not re-confirmed recently) or former, plus corporate officers, permanent representatives and statutory auditors. Never includes birth dates or national numbers. |
| get_company_financials kbo, year |
Parsed NBB figures and derived ratios per fiscal year, sector-aware. The free scope returns the latest fiscal year only; older years are gated and the tool says so in its note rather than returning silence. |
| get_extraction_status kbo |
How many gazette acts are on file for this company and how many have been extracted, plus the queue state. Call it whenever an act timeline looks empty or short. |
Every tool result carries a source attribution string
and, where relevant, a dossierUrl a human can open.
National register numbers are stripped from every field before
serialization.
| GET /healthz | Liveness. Always 200, no dependencies, never cached |
| GET /health/status | Readiness: database, Argus views and job-server probes plus data freshness. 200 even when degraded |
| GET /version | Release id, commit hash and build timestamp of the running build |
| GET /sitemap.xml | Sitemap index; sub-sitemaps are crawl-priority ordered with real lastmod dates |
| GET /robots.txt | Crawler policy, including the named AI-crawler sections |
| GET /insolventies/rss.xml | Newest insolvency publications as RSS 2.0 |
| GET /badge/{kbo}.svg | Embeddable status badge for one company |
| GET /export/company/{kbo}/financials.csv | Parsed annual-account lines for one company as CSV |
| GET /kbo/{kbo} | 301 to the canonical dossier URL. Handy for deep links when you only hold a number |
Breaking changes get a new path version and are announced to every key
holder by mail before they ship. Additive changes (new fields, new MCP
tools) land in v1 and are listed here, so write
tolerant parsers.
| 2026-08-09 | REST error responses now always carry a JSON body: 404 and 429 used to return an empty body, which the site's not-found handler turned into an HTML page. No field or route changed. First publication of this reference. |
| 2026-07 | MCP endpoint live with six read-only tools, key-gated, 60 requests per minute per key. |
| 2026-06 | /api/v1 live: dossier, lifecycle, rollup and search, key-gated. |
Short marketing overview of the same API: the API page. Where the data comes from: sources. How we score: methodology. Browse the corpus: company search.