Naar de inhoud
Subsido

Actueel blijven

Wijzigingen en versies

Overheidsportalen zeggen wat vandaag geldt. De change feed zegt wat er veranderde sinds je laatst keek: een nieuwe oproep, een deadline die van 1 naar 15 oktober schoof, een verhoogd maximum, een grootteregel die nu ook grote ondernemingen toelaat.

Versies en events

Telkens de inhoud van een maatregel verandert, wordt een nieuwe versie geschreven, met de verschillen per veld tegenover de vorige. Een bron opnieuw nakijken zonder wijziging schrijft niets, dus een versie is altijd een echte wijziging. Elke versie levert één event op in de change feed, getypeerd naar de belangrijkste wijziging en met elke categorie die ze raakte. Versies blijven voor altijd bewaard, events 400 dagen.

De change feed

Developer en hogerGET /v1/changes vraagt de functie change_feed.

curl "https://api.subsido.be/v1/changes?since=2026-09-01&type=subsidy.created,subsidy.deadline_changed&region=flanders" \  -H "Authorization: Bearer sb_live_..."
ParameterBetekenis
sinceRFC 3339 of YYYY-MM-DD (het begin van die dag in Brussel): events vanaf dat moment. Hoogstens 400 dagen terug; versies gaan verder terug.
typeKommalijst van eventtypes. Een event past als zijn hoofdtype of een van zijn categorieën in de lijst staat. match.*-types worden geweigerd: die staan nooit in de publieke feed.
subsidyHet id van één maatregel (niet de slug).
sourceKommalijst van bron-id’s. Past ook op de eigen actualiteitsevents van de bron.
regionKommalijst van gewesten: events over maatregelen daar, en over federale en Europese maatregelen, die overal gelden. Bronevents gaan erdoor.
limit, cursorPaginagrootte en positie; zie paginering.

Events komen het oudste eerst, in de volgorde van seq. De pagina is { data, pagination, meta }, en meta.latest_seq is de nieuwste seq in de hele feed, zodat je ziet hoe ver je achterloopt.

{
  "id": "chg_06f8s2k1c9t4r7m3q5v0x8z2yw",
  "seq": 18422,
  "type": "subsidy.status_changed",
  "categories": [
    "subsidy.status_changed",
    "subsidy.deadline_changed"
  ],
  "subject": "subsidy",
  "subject_id": "eu:HORIZON-EIC-2026-ACCELERATOR-01",
  "version": 4,
  "changes": [
    {
      "field": "status",
      "before": "open",
      "after": "closed"
    },
    {
      "field": "application_window.closes_at",
      "before": "2026-10-01T17:00:00+02:00",
      "after": "2026-09-20T17:00:00+02:00"
    }
  ],
  "summary": {
    "title": {
      "nl": null,
      "fr": null,
      "en": "EIC Accelerator",
      "de": null
    },
    "status": "closed",
    "instrument_type": "grant",
    "issuer": "European Commission",
    "closes_at": "2026-09-20T17:00:00+02:00",
    "regions": [],
    "topics": [
      "innovation",
      "growth_scaleup"
    ],
    "url": "https://ec.europa.eu/info/funding-tenders/opportunities/portal/screen/opportunities/topic-details/HORIZON-EIC-2026-ACCELERATOR-01",
    "source_id": "eu_funding_tenders"
  },
  "occurred_at": "2026-09-27T06:12:40+02:00"
}
VeldBetekenis
idHet id van het event, chg_…. Hetzelfde id is de id van de webhooklevering.
seqStijgt over de hele feed. De cursor is erop gebouwd.
typeHet hoofdtype van het event.
categoriesElke categorie die de versie raakte. Een versie die status en deadline samen wijzigde, heeft type subsidy.status_changed met beide categorieën.
subject, subject_idsubsidy en het id van de maatregel, of source en het id van de bron.
versionDe versie van de maatregel die dit event opleverde, of null voor events die geen versie zijn (nakende deadline, bronevents).
changes[]{ field, before, after } voor elk eindveld dat verschilt. Zie verder.
summaryGenoeg om te handelen zonder tweede request: title (in elke taal), status, instrument_type, issuer, closes_at, regions, topics, de officiële url en source_id. Events over een nakende deadline voegen days_left en threshold_days toe; bronevents bevatten freshness en previous.
occurred_atWanneer de wijziging geregistreerd werd, in Brusselse tijd.

Eventtypes en categorieën

TypeWanneer
subsidy.createdEen maatregel verschijnt voor het eerst.
subsidy.status_changedHet veld status veranderde: geopend, gesloten, gepauzeerd, budget op.
subsidy.deadline_changedAlles onder application_window: een deadline, de openingsdatum, doorlopend indienen, uitputting van het budget.
subsidy.funding_changedAlles onder funding: percentages, bedragen, plafonds, het programmabudget.
subsidy.eligibility_changedAlles onder eligibility behalve thema’s: soorten aanvragers, groottes, sectoren, regels, kostensoorten.
subsidy.updatedAl de rest: titels, samenvattingen, thema’s, links, de rechtsgrond.
subsidy.closing_soonDe deadline van een open maatregel ligt 14 dagen verder, en opnieuw op 3 dagen. Geen versie: een controle elk uur verstuurt het één keer per maatregel, deadline en drempel.
subsidy.removedDe bron vermeldt de maatregel niet meer. Hij verschijnt niet meer in lijsten, tenzij je include_withdrawn meegeeft.
source.staleEen bron ging van fresh of delayed naar stale, unavailable of unreadable.
source.recoveredZe is terug.
match.created, match.status_changed, match.removedWatchlist-events, alleen voor de webhooks van de eigenaar. Zie watchlists.

Het hoofdtype van een versie is de belangrijkste categorie die ze raakte, in de volgorde status, deadline, financiering, voorwaarden, overige. Filter of abonneer je op een categorie, niet alleen op het hoofdtype, anders mis je de gewijzigde deadline die samen met een statuswijziging kwam.

Verschillen per veld

  • field is een pad met punten naar een eindveld: status, application_window.closes_at, funding.amount_max, titles.nl. Arrays worden in hun geheel vergeleken, dus een gewijzigde lijst gewesten is één wijziging met de oude en de nieuwe lijst.
  • De lijst regels wordt regel per regel vergeleken op hun id: eligibility.rules[age_max] met de regel ervoor en erna (null als hij toegevoegd of verwijderd werd). Alleen een andere herkomst van een regel, zoals een nieuwe controledatum, is geen wijziging van de regel.
  • Administratieve velden worden wel geversioneerd maar nooit gemeld: provenance.last_checked_at, provenance.content_hash, provenance.first_seen_at en provenance.fields. Een versie waarvan alleen die velden verschillen, levert geen event op.

Verstreken datums

Elk uur normaliseren we elk actueel record opnieuw tegen het huidige tijdstip. Een oproep waarvan de deadline verstreken is, wordt closed, een aangekondigde oproep die geopend is, wordt open, en closes_at schuift door naar de volgende deadline van een oproep in meerdere rondes. Elk daarvan is een nieuwe versie met oorzaak date_passed en een gewoon event, meestal subsidy.status_changed of subsidy.deadline_changed. Dezelfde controle elk uur verstuurt subsidy.closing_soon.

De feed volgen

Doe de eerste call met since (of zonder, vanaf het oudste bewaarde event) en volg daarna next_cursor. Elke pagina heeft er een, ook de laatste: is has_more false, dan ben je bij, en met dezelfde cursor begint de volgende poll. Bewaar hem samen met het werk dat hij dekt, dan gaat een herstart precies verder waar hij stopte.

Er wordt niets overgeslagen en niets herhaald, ook al schrijft een importrun veel events tegelijk weg en kunnen runs overlappen: een event krijgt zijn plaats in de feed (zijn seq) pas nadat het vastgelegd is, dus een event dat laat vastgelegd wordt, komt na alles wat je al gelezen hebt. Een overlapvenster of een lijst van geziene id’s is niet nodig. seq is de volgorde van de feed; occurred_at is wanneer de wijziging vastgesteld werd en kan iets ouder zijn dan dat van een event ervoor.

JavaScript
let cursor = await loadCursor(); // null on the very first run

async function poll() {
  for (;;) {
    const url = new URL("https://api.subsido.be/v1/changes");
    url.searchParams.set("limit", "100");
    if (cursor) url.searchParams.set("cursor", cursor);
    else url.searchParams.set("since", "2026-09-01");
    const res = await fetch(url, {
      headers: { Authorization: `Bearer ${process.env.SUBSIDY_API_KEY}` },
    });
    const page = await res.json();
    if (!res.ok) throw new Error(page.error.code);
    for (const e of page.data) await handle(e);
    cursor = page.pagination.next_cursor; // always set
    await saveCursor(cursor);
    if (!page.pagination.has_more) return; // caught up; poll again later
  }
}

Of laat ons jou verwittigen

Webhooks sturen elk event naar je endpoint zodra het gebeurt, met dezelfde filters, zodat je de feed alleen nog leest om een achterstand in te halen.

Versies en historiek

Pro en hogerVersies en as_of vragen de functies history en as_of.

GET /v1/subsidies/{id}/versions geeft de versies van een maatregel, de nieuwste eerst: { version, valid_from, valid_to, cause, content_hash, changes }. GET /v1/subsidies/{id}/versions/{version} geeft het record zoals het was, en GET /v1/subsidies/{id}?as_of= de versie die op een bepaald moment gold. Voorbeelden staan bij maatregelen zoeken.

Waarom een versie geschreven werd

causeBetekenis
source_changeDe bron publiceerde iets anders.
date_passedDe controle elk uur: een deadline of een openingsdatum is verstreken.
reprocessWe normaliseerden de laatste lezing van de bron opnieuw, na een correctie in hoe ze gelezen wordt.
withdrawnDe bron vermeldt de maatregel niet meer (dit geeft subsidy.removed).
closed_at_sourceDe bron vermeldt hem niet meer, en bij die bron betekent een ontbrekend item dat de oproep gesloten is.
restoredEen maatregel die de bron niet meer vermeldde, is terug.
curation, mergeVoorbehouden voor een correctie door een persoon en voor twee records die samengevoegd worden. Oude id’s van een samengevoegd record blijven werken; zie merged_from.

Met versies en de change feed wordt “wat staat er open?” ook “wat veranderde er, wanneer, en wat wisten we op de dag van ons advies?”. Zie prijzen.