Skip to content
Subsido

Start

Quickstart

Five minutes from nothing to a list of measures a real company could apply for, and the reasons.

1. Get a key

Sign in with Google, choose a plan in the dashboard (from €20 a month excluding VAT; see pricing), and create a key under API keys. A key is shown once, and only its hash is stored, so copy it somewhere safe. Keys look like sb_live_....

You can create a key before you choose a plan, so the integration can be set up first. Until a plan is active, that key answers 402 subscription_required.

Check that it works. GET /v1/key answers with your plan and this month’s usage:

curl "https://api.subsido.be/v1/key" -H "Authorization: Bearer sb_live_..."

What can a small company in Flanders apply for today? Filter by region (which includes the national and EU measures that apply everywhere), by the company’s size, and by status:

curl "https://api.subsido.be/v1/subsidies?region=flanders&company_size=small&status=open,continuous,forthcoming&limit=5" \  -H "Authorization: Bearer sb_live_..."
JavaScript
const url = new URL("https://api.subsido.be/v1/subsidies");
url.search = new URLSearchParams({
  region: "flanders",
  company_size: "small",
  status: "open,continuous,forthcoming",
  topic: "digitalisation",
  lang: "en",
  limit: "5",
}).toString();

const res = await fetch(url, {
  headers: { Authorization: `Bearer ${process.env.SUBSIDY_API_KEY}` },
});
const body = await res.json();
if (!res.ok) throw new Error(`${body.error.code}: ${body.error.message}`);

for (const m of body.data) {
  console.log(m.status, m.closes_at ?? "no deadline", m.title, m.links.official);
}
Python
import os, requests

r = requests.get(
    "https://api.subsido.be/v1/subsidies",
    params={
        "region": "flanders",
        "company_size": "small",
        "status": "open,continuous,forthcoming",
        "topic": "digitalisation",
        "lang": "en",
        "limit": 5,
    },
    headers={"Authorization": f"Bearer {os.environ['SUBSIDY_API_KEY']}"},
    timeout=15,
)
body = r.json()
if not r.ok:
    raise RuntimeError(f"{body['error']['code']}: {body['error']['message']}")
for m in body["data"]:
    print(m["status"], m["closes_at"], m["title"], m["links"]["official"])

Each row is a compact record. Here is one, with illustrative values:

{
  "id": "federal:investeringsaftrek",
  "slug": "investeringsaftrek",
  "title": "Investment deduction",
  "summary": "Tax deduction from FOD Financiën for companies, self-employed people and farmers in Belgium. Covers 10% to 40% of eligible costs. Applications accepted at any time.",
  "summary_origin": "generated",
  "titles": {
    "nl": "Investeringsaftrek",
    "fr": "Déduction pour investissement",
    "en": "Investment deduction",
    "de": null
  },
  "status": "continuous",
  "instrument_type": "tax_deduction",
  "issuer": {
    "id": "fod-financien",
    "name": "FOD Financiën",
    "government_level": "federal",
    "jurisdiction": "be",
    "url": "https://financien.belgium.be"
  },
  "scope": "national",
  "regions": [],
  "topics": [
    "investment",
    "digitalisation",
    "energy_efficiency",
    "renewable_energy"
  ],
  "company_sizes": [],
  "opens_at": null,
  "closes_at": null,
  "rolling": true,
  "rate_max": 40,
  "amount_max": null,
  "annual_cap": null,
  "rules_basis": "curated",
  "source_id": "curated_federal",
  "rights_mode": "facts_only",
  "version": 2,
  "last_changed_at": "2026-09-27T05:52:40+02:00",
  "last_checked_at": "2026-09-27T06:00:12+02:00",
  "freshness": {
    "state": "fresh",
    "last_successful_fetch": "2026-09-27T06:00:12+02:00",
    "expected_refresh_seconds": 86400,
    "stale_after_seconds": 259200
  },
  "links": {
    "self": "https://api.subsido.be/v1/subsidies/federal:investeringsaftrek",
    "versions": "https://api.subsido.be/v1/subsidies/federal:investeringsaftrek/versions",
    "official": "https://financien.belgium.be/nl/ondernemingen/vennootschapsbelasting/belastingvoordelen/investeringsaftrek",
    "web": "https://subsido.be/en/grants/investeringsaftrek"
  }
}
  • title and summary are in the language you asked for with lang, falling back to whatever the source published. titles has every language there is.
  • links.official is the authority’s own page. Show it next to anything you display: the authority, not this API, is where an application is made and decided.
  • freshness says when the source was last read successfully and whether that is within its expected schedule.

GET /v1/subsidies/{id} with that id (or with its slug) returns the full record, with the funding tiers, every deadline and the eligibility rules.

3. Match a company and a project

Search answers “what exists”. Matching answers “what fits this company”: send what you know about the company and the project, and every measure is evaluated against it.

curl -X POST "https://api.subsido.be/v1/match" \  -H "Authorization: Bearer sb_live_..." \  -H "Content-Type: application/json" \  -d '{"company":{"postcode":"9000","employees":12,"turnover_eur":1500000,"legal_form":"bv","nace":["62.010"]},"project":{"topics":["digitalisation","investment"],"budget_eur":25000,"planned_start":"2026-11-01"},"language":"en","limit":10}'
JavaScript
const res = await fetch("https://api.subsido.be/v1/match", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.SUBSIDY_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "company": {
      "postcode": "9000",
      "employees": 12,
      "turnover_eur": 1500000,
      "legal_form": "bv",
      "nace": [
        "62.010"
      ]
    },
    "project": {
      "topics": [
        "digitalisation",
        "investment"
      ],
      "budget_eur": 25000,
      "planned_start": "2026-11-01"
    },
    "language": "en",
    "limit": 10
  }),
});
const result = await res.json();
if (!res.ok) throw new Error(`${result.error.code}: ${result.error.message}`);

for (const m of result.matches) {
  console.log(m.match_status, m.subsidy.title, m.estimate?.basis ?? "");
  for (const u of m.unknowns) console.log("  still needed:", u.request_path, u.question);
}

The answer lists the matches best first, each with the result of every rule (reasons), the facts still missing (unknowns) and an indicative amount (estimate). It also echoes what was derived from your input: the postcode 9000 became Flanders and East Flanders, 12 employees and €1,500,000 turnover became a small company, and the legal form bv became an applicant type and legal personality. The matching page walks through a full response.

Four statuses, never “eligible”

likely_eligible, possibly_eligible, needs_review and not_eligible (the last only when you ask for it). The competent authority decides eligibility and awards; a match says how far the published conditions and your facts agree.

Next