Aller au contenu
Subsido

Référence API

Chaque endpoint, à essayer tout de suite

Cliquez sur Envoyer et voyez la vraie API répondre, matching d'entreprise compris. Pas besoin de clé pour explorer : les appels passent par un proxy sur notre serveur, limité à dix lignes.

URL de base https://api.subsido.be/v1 · authentification Bearer · documentation complète

Document OpenAPI 3.1Sans clé. Générez un client, ou importez-le dans Postman ou Insomnia.

Essayez

Les routes ouvertes et les principales routes de données, via le proxy : dix lignes au plus et un corps de matching de 4 Ko au plus. Les routes qui demandent une formule supérieure, comme le flux de modifications, les versions et le matching par lot, ne sont pas dans l'explorateur.

GET/v1/subsidiesDeveloper

Lister et rechercher des mesures. Chaque filtre est facultatif ; region inclut les mesures fédérales et européennes qui s'appliquent partout.

q
mots, correspondance par préfixe, toute langue
region
flanders, brussels, wallonia
topic
identifiants de thèmes, séparés par des virgules
company_size
micro, small, medium, large
instrument_type
grant, loan, tax_deduction, ...
status
open, continuous, forthcoming, ...
lang
nl, fr, en
view
compact ou full

S'exécute sur l'API réelle, via un proxy sur notre serveur. Aucune clé n'est nécessaire : les listes sont limitées à dix lignes et le corps d'un matching à 4 Ko. Avec votre propre clé, ces limites ne s'appliquent pas.

Toutes les opérations

Générées à partir du document OpenAPI de l'API. Les descriptions sont en anglais.

Subsido APIv1.0.0 · 32 opérations, issues de /v1/openapi.json.

Service

GET/v1/healthsans cléHealth

Database, sources not fresh, and what sign-in the site offers.

  • 200Success
GET/v1/planssans cléPlans and prices

The entitlement table the API enforces, with list prices in euros.

  • 200Success
GET/v1/taxonomysans cléVocabularies

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/coveragesans cléCoverage

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/sourcessans cléSources

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}sans cléOne source

A source with its recent runs.

Paramètres de GET /v1/sources/{id}
ParamètreEmplacementTypeDescription
id*pathstringA 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.

Paramètres de GET /v1/subsidies
ParamètreEmplacementTypeDescription
qquerystringWords in any language; each must match the start of a word (prefix search, accents ignored).
regionquerystringMeasures available to a company in these regions: the region's own plus national and EU measures, which apply everywhere.
topicquerystringMeasures tagged with any of these topics.
company_sizequerymicro | small | medium | largeThe company's size: measures naming it, and those that do not restrict size.
instrument_typequerystring
statusquerystringDefault: every status. `open,continuous,forthcoming` is what can be applied for.
government_levelquerystring
scopequerystring
sourcequerystringComma list of source ids (GET /v1/sources).
issuerquerystringComma list of issuer ids (`vlaio`, `european-commission`, ...).
nacequerystringA company's NACE code (62.010): measures with no sector restriction, or one covering it.
programmequerystringEU programme code: HORIZON, DIGITAL, LIFE, SMP, ...
deadline_beforequerystringRFC 3339, or YYYY-MM-DD meaning the end of that Brussels day.
deadline_afterquerystring
updated_sincequerystringChanged on or after this instant.
include_withdrawnquerybooleanInclude measures the source no longer lists.
sortqueryrelevance | deadline | updated | titleDefault: relevance with `q`, deadline (soonest first, none last) without.
viewquerycompact | fullDefault compact.
langquerynl | fr | enLanguage of `title`, `summary` and links. Default en.
limitqueryintegerPage size, up to the plan's maximum (Developer 100, Pro and Business 200, Enterprise 500). Above it is an error, never a silent truncation.
cursorquerystringFrom `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.

Paramètres de GET /v1/subsidies/{id}
ParamètreEmplacementTypeDescription
id*pathstringThe measure's id (`vlaio:kmo-portefeuille`, `eu:HORIZON-EIC-2026-ACCELERATOR-01`) or slug.
langquerynl | fr | enLanguage of `title`, `summary` and links. Default en.
as_ofquerystringRFC 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.

Paramètres de GET /v1/subsidies/{id}/versions
ParamètreEmplacementTypeDescription
id*pathstringThe 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.

Paramètres de GET /v1/subsidies/{id}/versions/{version}
ParamètreEmplacementTypeDescription
id*pathstringThe measure's id (`vlaio:kmo-portefeuille`, `eu:HORIZON-EIC-2026-ACCELERATOR-01`) or slug.
version*pathintegerThe version number.
langquerynl | fr | enLanguage 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.

Paramètres de GET /v1/changes
ParamètreEmplacementTypeDescription
sincequerystringStart here on a first call (at most 400 days back); afterwards use the cursor.
typequerystring
subsidyquerystringOne measure's events.
sourcequerystring
regionquerystring
limitqueryintegerPage size, up to the plan's maximum (Developer 100, Pro and Business 200, Enterprise 500). Above it is an error, never a silent truncation.
cursorquerystringFrom `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.

Corps de la requête 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.

Corps de la requête 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.

Paramètres de GET /v1/export/subsidies.ndjson
ParamètreEmplacementTypeDescription
langquerynl | fr | enLanguage of `title`, `summary` and links. Default en.
include_withdrawnqueryboolean
  • 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.

Corps de la requête 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
Paramètres de GET /v1/watchlists/{id}
ParamètreEmplacementTypeDescription
id*pathstringA `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
Paramètres de PATCH /v1/watchlists/{id}
ParamètreEmplacementTypeDescription
id*pathstringA `wl_` id.

Corps de la requête 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
Paramètres de DELETE /v1/watchlists/{id}
ParamètreEmplacementTypeDescription
id*pathstringA `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
Paramètres de GET /v1/watchlists/{id}/companies
ParamètreEmplacementTypeDescription
id*pathstringA `wl_` id.
limitqueryintegerPage size, up to the plan's maximum (Developer 100, Pro and Business 200, Enterprise 500). Above it is an error, never a silent truncation.
cursorquerystringFrom `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.

Paramètres de POST /v1/watchlists/{id}/companies
ParamètreEmplacementTypeDescription
id*pathstringA `wl_` id.

Corps de la requête 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
Paramètres de DELETE /v1/watchlists/{id}/companies/{reference}
ParamètreEmplacementTypeDescription
id*pathstringA `wl_` id.
reference*pathstringYour 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.

Paramètres de GET /v1/watchlists/{id}/matches
ParamètreEmplacementTypeDescription
id*pathstringA `wl_` id.
companyquerystringOne company's reference.
include_not_eligiblequeryboolean
limitqueryintegerUp 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.

Paramètres de GET /v1/webhooks
ParamètreEmplacementTypeDescription
limitqueryintegerPage size, up to the plan's maximum (Developer 100, Pro and Business 200, Enterprise 500). Above it is an error, never a silent truncation.
cursorquerystringFrom `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.

Corps de la requête 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
Paramètres de DELETE /v1/webhooks/{id}
ParamètreEmplacementTypeDescription
id*pathstringA `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.

Paramètres de POST /v1/webhooks/{id}/enable
ParamètreEmplacementTypeDescription
id*pathstringA `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.

Paramètres de POST /v1/webhooks/{id}/rotate
ParamètreEmplacementTypeDescription
id*pathstringA `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.

Paramètres de POST /v1/webhooks/{id}/test
ParamètreEmplacementTypeDescription
id*pathstringA `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.

Paramètres de GET /v1/webhooks/{id}/deliveries
ParamètreEmplacementTypeDescription
id*pathstringA `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.

Corps de la requête object

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/list"
}
  • 200Success
  • 401unauthorized
  • 429rate_limit_exceeded, quota_exceeded
  • 500internal_error
  • 504timeout

Le contrat

Ce qui vaut pour chaque endpoint, pour que vous ne l'appreniez qu'une fois.

Une seule enveloppe

Les listes renvoient { data, pagination, meta } et une ressource { data, meta } ; les routes de matching et quelques routes de service renvoient leurs propres objets documentés. Les erreurs renvoient toujours { error: { code, message, request_id, details } }. Basez votre logique sur code : il ne change pas.

Pagination par curseur

limit et cursor, fondés sur la valeur de tri plus un identifiant de départage, si bien que la page 2 000 coûte autant que la page 1. Un limit au-delà de votre formule est une erreur, jamais une troncature silencieuse.

Tous les champs présents

Une valeur sans objet vaut null et n'est jamais omise : une ligne a les mêmes champs sur chaque page.

Paramètres stricts

Un paramètre inconnu ou répété, ou une valeur hors vocabulaire, donne une erreur 400 qui le nomme. Une faute de frappe n'élargit jamais un résultat en silence.

Provenance

Chaque mesure indique sa source, la date de sa dernière vérification et un lien vers la page de l'autorité elle-même.

Des fonctions, pas des noms de formule

Un appel refusé nomme la fonction et la formule la moins chère qui y aurait répondu. Les en-têtes RateLimit montrent votre quota mensuel avant que vous l'atteigniez.