API-referentie
Elk endpoint, meteen uit te proberen
Druk op Verstuur en zie de echte API antwoorden, een bedrijfsmatch inbegrepen. Rondkijken kan zonder sleutel: de calls lopen via een proxy op onze server, beperkt tot tien rijen.
Basis-URL https://api.subsido.be/v1 · Bearer-authenticatie · volledige documentatie
Probeer het
De open routes en de kernroutes voor data, via de proxy: hoogstens tien rijen en een matchbody van hoogstens 4 KB. Routes die een hoger plan vragen, zoals de change feed, versies en bulkmatching, zitten niet in de verkenner.
/v1/subsidiesDeveloperMaatregelen oplijsten en doorzoeken. Elke filter is optioneel; region bevat ook de federale en Europese maatregelen die overal gelden.
- q
- woorden, prefixmatch, in elke taal
- region
- flanders, brussels, wallonia
- topic
- thema-id's, gescheiden door komma's
- company_size
- micro, small, medium, large
- instrument_type
- grant, loan, tax_deduction, ...
- status
- open, continuous, forthcoming, ...
- lang
- nl, fr, en
- view
- compact of full
Loopt tegen de echte API, via een proxy op onze server. Geen sleutel nodig: lijsten zijn beperkt tot tien rijen en een matchbody tot 4 KB. Met je eigen sleutel gelden die beperkingen niet.
Alle operaties
Rechtstreeks uit het OpenAPI-document van de API. De beschrijvingen zijn in het Engels.
Subsido APIv1.0.0 · 32 operaties, uit /v1/openapi.json.
Service
GET/v1/healthgeen sleutelHealth
Database, sources not fresh, and what sign-in the site offers.
- 200Success
GET/v1/plansgeen sleutelPlans and prices
The entitlement table the API enforces, with list prices in euros.
- 200Success
GET/v1/taxonomygeen sleutelVocabularies
Every closed vocabulary with labels in Dutch, French and English: topics, regions, provinces, instrument types, statuses, sizes, applicant types, cost types, rule fields (with the question asked when one is unknown), operators and event types.
- 200Success
- 400invalid_parameter
- 429rate_limit_exceeded
GET/v1/coveragegeen sleutelCoverage
How many measures, by status, source, instrument, level, region and topic.
- 200Success
- 400invalid_parameter
- 429rate_limit_exceeded
GET/v1/keyThe calling key
The key's plan, what it allows, and this month's requests and match evaluations, in the `{data, meta}` envelope. The right first request.
- 200Success
- 401unauthorized
- 429rate_limit_exceeded, quota_exceeded
- 500internal_error
- 504timeout
Sources
GET/v1/sourcesgeen sleutelSources
Every source the API serves measures from, its licence and reuse mode, and how fresh it is. A source that is switched off is not listed.
- 200Success
- 400invalid_parameter
- 429rate_limit_exceeded
GET/v1/sources/{id}geen sleutelOne source
A source with its recent runs.
| Parameter | Locatie | Type | Beschrijving |
|---|---|---|---|
| id* | path | string | A source id. |
- 200Success
- 400invalid_parameter
- 404source_not_found
- 429rate_limit_exceeded
Subsidies
GET/v1/subsidiesList and search measures
Filter, search and page through every servable measure. Cursor paging; every list is ordered and complete.
| Parameter | Locatie | Type | Beschrijving |
|---|---|---|---|
| q | query | string | Words in any language; each must match the start of a word (prefix search, accents ignored). |
| region | query | string | Measures available to a company in these regions: the region's own plus national and EU measures, which apply everywhere. |
| topic | query | string | Measures tagged with any of these topics. |
| company_size | query | micro | small | medium | large | The company's size: measures naming it, and those that do not restrict size. |
| instrument_type | query | string | |
| status | query | string | Default: every status. `open,continuous,forthcoming` is what can be applied for. |
| government_level | query | string | |
| scope | query | string | |
| source | query | string | Comma list of source ids (GET /v1/sources). |
| issuer | query | string | Comma list of issuer ids (`vlaio`, `european-commission`, ...). |
| nace | query | string | A company's NACE code (62.010): measures with no sector restriction, or one covering it. |
| programme | query | string | EU programme code: HORIZON, DIGITAL, LIFE, SMP, ... |
| deadline_before | query | string | RFC 3339, or YYYY-MM-DD meaning the end of that Brussels day. |
| deadline_after | query | string | |
| updated_since | query | string | Changed on or after this instant. |
| include_withdrawn | query | boolean | Include measures the source no longer lists. |
| sort | query | relevance | deadline | updated | title | Default: relevance with `q`, deadline (soonest first, none last) without. |
| view | query | compact | full | Default compact. |
| lang | query | nl | fr | en | Language of `title`, `summary` and links. Default en. |
| limit | query | integer | Page size, up to the plan's maximum (Developer 100, Pro and Business 200, Enterprise 500). Above it is an error, never a silent truncation. |
| cursor | query | string | From `pagination.next_cursor`. Opaque. |
- 200Success
- 400invalid_parameter, invalid_cursor
- 401unauthorized
- 429rate_limit_exceeded, quota_exceeded
- 500internal_error
- 504timeout
GET/v1/subsidies/{id}One measure
The full record. `as_of` (Pro and above) returns the version that was current at that instant.
| Parameter | Locatie | Type | Beschrijving |
|---|---|---|---|
| id* | path | string | The measure's id (`vlaio:kmo-portefeuille`, `eu:HORIZON-EIC-2026-ACCELERATOR-01`) or slug. |
| lang | query | nl | fr | en | Language of `title`, `summary` and links. Default en. |
| as_of | query | string | RFC 3339, or YYYY-MM-DD meaning the end of that Brussels day. Pro and above. |
- 200Success
- 400invalid_parameter
- 401unauthorized
- 403plan_required
- 404subsidy_not_found, version_not_found
- 429rate_limit_exceeded, quota_exceeded
- 500internal_error
- 504timeout
History
GET/v1/subsidies/{id}/versionsVersions of a measure
Every version, newest first, with the field-level changes that made it. Pro and above.
| Parameter | Locatie | Type | Beschrijving |
|---|---|---|---|
| id* | path | string | The measure's id (`vlaio:kmo-portefeuille`, `eu:HORIZON-EIC-2026-ACCELERATOR-01`) or slug. |
- 200Success
- 400invalid_parameter
- 401unauthorized
- 403plan_required
- 404subsidy_not_found
- 429rate_limit_exceeded, quota_exceeded
- 500internal_error
- 504timeout
GET/v1/subsidies/{id}/versions/{version}One version
The record as it was in that version. Pro and above.
| Parameter | Locatie | Type | Beschrijving |
|---|---|---|---|
| id* | path | string | The measure's id (`vlaio:kmo-portefeuille`, `eu:HORIZON-EIC-2026-ACCELERATOR-01`) or slug. |
| version* | path | integer | The version number. |
| lang | query | nl | fr | en | Language of `title`, `summary` and links. Default en. |
- 200Success
- 400invalid_parameter
- 401unauthorized
- 403plan_required
- 404subsidy_not_found, version_not_found
- 429rate_limit_exceeded, quota_exceeded
- 500internal_error
- 504timeout
Changes
GET/v1/changesThe change feed
Every new measure, every version (typed by its most significant change, with every category it touched), closing-soon reminders and source freshness events, in order. Page with `cursor` while `has_more` is true. Every page carries `next_cursor`, the last one too: `has_more: false` with a cursor means nothing more for now, so poll again later with that cursor and get only what is new. An empty page returns the cursor it was given (or, on a first call, one at the newest event). Developer and above.
| Parameter | Locatie | Type | Beschrijving |
|---|---|---|---|
| since | query | string | Start here on a first call (at most 400 days back); afterwards use the cursor. |
| type | query | string | |
| subsidy | query | string | One measure's events. |
| source | query | string | |
| region | query | string | |
| limit | query | integer | Page size, up to the plan's maximum (Developer 100, Pro and Business 200, Enterprise 500). Above it is an error, never a silent truncation. |
| cursor | query | string | From `pagination.next_cursor` of any page, the last one included. Opaque. |
- 200Success
- 400invalid_parameter, invalid_cursor
- 401unauthorized
- 403plan_required
- 429rate_limit_exceeded, quota_exceeded
- 500internal_error
- 504timeout
Matching
POST/v1/matchMatch a company and a project
Which measures plausibly fit, why (every rule's pass, fail or unknown with its provenance), what is still unknown (as questions, ranked by how many matches they would settle), and an indicative amount. Statuses: likely_eligible, possibly_eligible, needs_review, not_eligible (only with include_not_eligible). Never "eligible": the competent authority decides. Best first: likely_eligible, then possibly_eligible and needs_review together, then not_eligible; within each by `score`, which weighs topic fit, the match status, rule confidence, whether the measure can be applied for now (open and continuous alike), and how close to the company it is decided (its own region, then national, then EU), less a little per unanswered question; the soonest deadline breaks a tie. `company.nace` takes NACE codes of at least two digits; a section letter is refused. One match evaluation.
Body van de request object
{
"company": {
"postcode": "9000",
"employees": 12,
"turnover_eur": 1500000,
"legal_form": "bv",
"nace": [
"62.010"
],
"founded_on": "2019-05-01"
},
"project": {
"topics": [
"digitalisation",
"cybersecurity"
],
"budget_eur": 25000,
"planned_start": "2026-11-01"
},
"language": "nl",
"limit": 10
}- 200Success
- 400invalid_parameter
- 401unauthorized
- 422invalid_body
- 429match_quota_exceeded, rate_limit_exceeded, quota_exceeded
- 500internal_error
- 504timeout
POST/v1/match/bulkMatch many companies
Up to 500 companies (Business) or 5,000 (Enterprise) in one request. One evaluation per valid company; an invalid one is answered with its own error. Business and above.
Body van de request object
{
"companies": [
{
"reference": "client-0042",
"company": {
"postcode": "9000",
"employees": 12,
"turnover_eur": 1500000,
"legal_form": "bv",
"nace": [
"62.010"
],
"founded_on": "2019-05-01"
},
"project": {
"topics": [
"digitalisation",
"cybersecurity"
],
"budget_eur": 25000,
"planned_start": "2026-11-01"
},
"language": "nl",
"limit": 10
}
]
}- 200Success
- 400invalid_parameter
- 401unauthorized
- 403plan_required
- 422invalid_body
- 429match_quota_exceeded, rate_limit_exceeded, quota_exceeded
- 500internal_error
- 504timeout
Export
GET/v1/export/subsidies.ndjsonThe whole catalogue
Every current measure as one full record per line. Business and above.
| Parameter | Locatie | Type | Beschrijving |
|---|---|---|---|
| lang | query | nl | fr | en | Language of `title`, `summary` and links. Default en. |
| include_withdrawn | query | boolean |
- 200Success
- 400invalid_parameter
- 401unauthorized
- 403plan_required
- 429rate_limit_exceeded, quota_exceeded
- 500internal_error
- 504timeout
Watchlists
GET/v1/watchlistsList watchlists
Business and above.
- 200Success
- 400invalid_parameter
- 401unauthorized
- 403plan_required
- 429rate_limit_exceeded, quota_exceeded
- 500internal_error
- 504timeout
POST/v1/watchlistsCreate a watchlist
A portfolio of companies re-evaluated whenever a measure changes; each difference is a match.* webhook event. Business and above.
Body van de request object
{
"name": "Manufacturing clients",
"language": "nl"
}- 201Success
- 401unauthorized
- 403plan_required
- 409conflict
- 422invalid_body
- 429rate_limit_exceeded, quota_exceeded
- 500internal_error
- 504timeout
GET/v1/watchlists/{id}One watchlist
| Parameter | Locatie | Type | Beschrijving |
|---|---|---|---|
| id* | path | string | A `wl_` id. |
- 200Success
- 401unauthorized
- 403plan_required
- 404watchlist_not_found
- 429rate_limit_exceeded, quota_exceeded
- 500internal_error
- 504timeout
PATCH/v1/watchlists/{id}Rename or change options
| Parameter | Locatie | Type | Beschrijving |
|---|---|---|---|
| id* | path | string | A `wl_` id. |
Body van de request object
{
"name": "Renamed"
}- 200Success
- 401unauthorized
- 403plan_required
- 404watchlist_not_found
- 422invalid_body
- 429rate_limit_exceeded, quota_exceeded
- 500internal_error
- 504timeout
DELETE/v1/watchlists/{id}Delete a watchlist
| Parameter | Locatie | Type | Beschrijving |
|---|---|---|---|
| id* | path | string | A `wl_` id. |
- 200Success
- 401unauthorized
- 403plan_required
- 404watchlist_not_found
- 429rate_limit_exceeded, quota_exceeded
- 500internal_error
- 504timeout
GET/v1/watchlists/{id}/companiesCompanies on a watchlist
| Parameter | Locatie | Type | Beschrijving |
|---|---|---|---|
| id* | path | string | A `wl_` id. |
| limit | query | integer | Page size, up to the plan's maximum (Developer 100, Pro and Business 200, Enterprise 500). Above it is an error, never a silent truncation. |
| cursor | query | string | From `pagination.next_cursor`. Opaque. |
- 200Success
- 400invalid_parameter
- 401unauthorized
- 403plan_required
- 404watchlist_not_found
- 429rate_limit_exceeded, quota_exceeded
- 500internal_error
- 504timeout
POST/v1/watchlists/{id}/companiesAdd or replace companies
Up to 1,000 per request, by your own reference. Each is evaluated at once and counts one match evaluation; invalid ones are listed in `rejected` and not stored.
| Parameter | Locatie | Type | Beschrijving |
|---|---|---|---|
| id* | path | string | A `wl_` id. |
Body van de request object
{
"companies": [
{
"reference": "client-0042",
"company": {
"postcode": "9000",
"employees": 12,
"turnover_eur": 1500000,
"legal_form": "bv",
"nace": [
"62.010"
],
"founded_on": "2019-05-01"
},
"project": {
"topics": [
"digitalisation",
"cybersecurity"
],
"budget_eur": 25000,
"planned_start": "2026-11-01"
}
}
]
}- 200Success
- 401unauthorized
- 403plan_required
- 404watchlist_not_found
- 422invalid_body
- 429match_quota_exceeded, rate_limit_exceeded, quota_exceeded
- 500internal_error
- 504timeout
DELETE/v1/watchlists/{id}/companies/{reference}Remove a company
| Parameter | Locatie | Type | Beschrijving |
|---|---|---|---|
| id* | path | string | A `wl_` id. |
| reference* | path | string | Your reference. |
- 200Success
- 401unauthorized
- 403plan_required
- 404watchlist_not_found, not_found
- 429rate_limit_exceeded, quota_exceeded
- 500internal_error
- 504timeout
GET/v1/watchlists/{id}/matchesCurrent matches
Every company's current matches, best first.
| Parameter | Locatie | Type | Beschrijving |
|---|---|---|---|
| id* | path | string | A `wl_` id. |
| company | query | string | One company's reference. |
| include_not_eligible | query | boolean | |
| limit | query | integer | Up to 5,000. |
- 200Success
- 400invalid_parameter
- 401unauthorized
- 403plan_required
- 404watchlist_not_found
- 429rate_limit_exceeded, quota_exceeded
- 500internal_error
- 504timeout
Webhooks
GET/v1/webhooksList webhooks
Pro and above.
| Parameter | Locatie | Type | Beschrijving |
|---|---|---|---|
| limit | query | integer | Page size, up to the plan's maximum (Developer 100, Pro and Business 200, Enterprise 500). Above it is an error, never a silent truncation. |
| cursor | query | string | From `pagination.next_cursor`. Opaque. |
- 200Success
- 400invalid_parameter
- 401unauthorized
- 403plan_required
- 429rate_limit_exceeded, quota_exceeded
- 500internal_error
- 504timeout
POST/v1/webhooksCreate a webhook
Deliveries are signed (Subsido-Signature: t=,v1=), retried at 1, 5, 30, 120 and 720 minutes, and the endpoint is switched off after 20 failures in a row (POST /v1/webhooks/{id}/enable turns it back on). The plan sets how many endpoints an account may have (`webhook_endpoints` in GET /v1/plans). Filters: event_types, sources, regions, topics, subsidy_ids, watchlists. Pro and above.
Body van de request object
{
"url": "https://hooks.example.com/subsidies",
"filters": {
"event_types": [
"subsidy.deadline_changed",
"subsidy.status_changed"
],
"regions": [
"flanders"
]
}
}- 201Success
- 400invalid_parameter
- 401unauthorized
- 403plan_required
- 404source_not_found, watchlist_not_found
- 429rate_limit_exceeded, quota_exceeded
- 500internal_error
- 504timeout
DELETE/v1/webhooks/{id}Delete a webhook
| Parameter | Locatie | Type | Beschrijving |
|---|---|---|---|
| id* | path | string | A `wh_` id. |
- 200Success
- 400invalid_parameter
- 401unauthorized
- 403plan_required
- 404webhook_not_found
- 429rate_limit_exceeded, quota_exceeded
- 500internal_error
- 504timeout
POST/v1/webhooks/{id}/enableSwitch a webhook back on
After 20 failed deliveries in a row an endpoint is switched off (`active: false`). This switches it on again with its failure count at zero, and answers the endpoint. Deliveries given up on while it was off are not resent; read them from the change feed.
| Parameter | Locatie | Type | Beschrijving |
|---|---|---|---|
| id* | path | string | A `wh_` id. |
- 200Success
- 400invalid_parameter
- 401unauthorized
- 403plan_required
- 404webhook_not_found
- 429rate_limit_exceeded, quota_exceeded
- 500internal_error
- 504timeout
POST/v1/webhooks/{id}/rotateRotate the signing secret
The old secret stops verifying at once.
| Parameter | Locatie | Type | Beschrijving |
|---|---|---|---|
| id* | path | string | A `wh_` id. |
- 200Success
- 400invalid_parameter
- 401unauthorized
- 403plan_required
- 404webhook_not_found
- 429rate_limit_exceeded, quota_exceeded
- 500internal_error
- 504timeout
POST/v1/webhooks/{id}/testSend a test delivery
Queues a signed ping.
| Parameter | Locatie | Type | Beschrijving |
|---|---|---|---|
| id* | path | string | A `wh_` id. |
- 200Success
- 400invalid_parameter
- 401unauthorized
- 403plan_required
- 404webhook_not_found
- 429rate_limit_exceeded, quota_exceeded
- 500internal_error
- 504timeout
GET/v1/webhooks/{id}/deliveriesRecent deliveries
The last 50, newest first.
| Parameter | Locatie | Type | Beschrijving |
|---|---|---|---|
| id* | path | string | A `wh_` id. |
- 200Success
- 400invalid_parameter
- 401unauthorized
- 403plan_required
- 404webhook_not_found
- 429rate_limit_exceeded, quota_exceeded
- 500internal_error
- 504timeout
MCP
POST/mcpModel Context Protocol server
Streamable HTTP, stateless: POST one JSON-RPC message (or a batch). Tools: search_subsidies, get_subsidy, match_company, explain_eligibility, list_changes, list_sources. Same key, limits and answers as the REST API.
Body van de request object
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list"
}- 200Success
- 401unauthorized
- 429rate_limit_exceeded, quota_exceeded
- 500internal_error
- 504timeout
Het contract
Wat voor elk endpoint geldt, zodat je het maar één keer hoeft te leren.
Eén envelop
Lijsten geven { data, pagination, meta } terug en één resource { data, meta }; de matchroutes en enkele serviceroutes geven hun eigen gedocumenteerde objecten. Fouten geven altijd { error: { code, message, request_id, details } }. Baseer je logica op code: die verandert niet.
Paginering met cursors
limit en cursor, op basis van de sorteerwaarde plus een id als tiebreaker, zodat pagina 2.000 even snel is als pagina 1. Een limit boven je plan geeft een fout, nooit een stille inkorting.
Elk veld aanwezig
Een waarde die niet van toepassing is, is null en wordt nooit weggelaten, dus elke rij heeft op elke pagina dezelfde velden.
Strikte parameters
Een onbekende of herhaalde parameter, of een waarde buiten de woordenlijst, geeft een 400 die hem bij naam noemt. Een tikfout verbreedt een resultaat nooit ongemerkt.
Herkomst
Elke maatregel vermeldt zijn bron, wanneer hij voor het laatst gecontroleerd is, en een link naar de pagina van de overheid zelf.
Functies, geen plannamen
Een geweigerde call noemt de functie en het goedkoopste plan dat hem wel had beantwoord. RateLimit-headers tonen je maandquotum voor je het bereikt.
