Rester à jour
Modifications et versions
Les portails publics disent ce qui s’applique aujourd’hui. Le flux de modifications dit ce qui a changé depuis votre dernier passage : un nouvel appel, une échéance déplacée du 1er au 15 octobre, un plafond relevé, une règle de taille qui admet désormais les grandes entreprises.
Versions et événements
Chaque fois que le contenu d’une mesure change, une nouvelle version est écrite, avec les différences champ par champ par rapport à la précédente. Relire une source sans changement n’écrit rien : une version correspond donc toujours à un vrai changement. Chaque version produit un événement dans le flux, typé selon le changement le plus important et listant chaque catégorie touchée. Les versions sont conservées indéfiniment, les événements pendant 400 jours.
Le flux de modifications
À partir de DeveloperGET /v1/changes demande la fonction change_feed.
curl "https://api.subsido.be/v1/changes?since=2026-09-01&type=subsidy.created,subsidy.deadline_changed®ion=flanders" \ -H "Authorization: Bearer sb_live_..."| Paramètre | Signification |
|---|---|
| since | RFC 3339 ou YYYY-MM-DD (le début de ce jour à Bruxelles) : les événements à partir de cet instant. Au plus 400 jours en arrière ; les versions remontent plus loin. |
| type | Liste de types d’événements séparés par des virgules. Un événement correspond si son type principal ou l’une de ses catégories figure dans la liste. Les types match.* sont refusés : ils ne figurent jamais dans le flux public. |
| subsidy | L’id d’une mesure (pas son slug). |
| source | Liste d’id de sources séparés par des virgules. Correspond aussi aux événements de fraîcheur de la source elle-même. |
| region | Liste de régions séparées par des virgules : les événements sur les mesures de ces régions, et sur les mesures fédérales et européennes, qui s’appliquent partout. Les événements de source passent. |
| limit, cursor | Taille et position de la page ; voir pagination. |
Les événements arrivent du plus ancien au plus récent, dans l’ordre de seq. La page est { data, pagination, meta }, et meta.latest_seq est le seq le plus récent de tout le flux : vous voyez ainsi votre retard.
{
"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"
}| Champ | Signification |
|---|---|
| id | L’id de l’événement, chg_…. C’est aussi l’id de la livraison webhook. |
| seq | Croissant sur tout le flux. Le curseur repose dessus. |
| type | Le type principal de l’événement. |
| categories | Chaque catégorie touchée par la version. Une version qui a changé à la fois le statut et l’échéance est de type subsidy.status_changed, avec les deux catégories. |
| subject, subject_id | subsidy et l’id de la mesure, ou source et l’id de la source. |
| version | La version de la mesure produite par cet événement, ou null pour les événements qui ne sont pas des versions (échéance proche, événements de source). |
| changes[] | { field, before, after } pour chaque champ terminal qui diffère. Voir plus bas. |
| summary | De quoi agir sans seconde requête : title (dans chaque langue), status, instrument_type, issuer, closes_at, regions, topics, l’url officielle et source_id. Les événements d’échéance proche ajoutent days_left et threshold_days ; les événements de source portent freshness et previous. |
| occurred_at | Quand la modification a été enregistrée, à l’heure de Bruxelles. |
Types et catégories d’événements
| Type | Quand |
|---|---|
| subsidy.created | Une mesure apparaît pour la première fois. |
| subsidy.status_changed | Le champ status a changé : ouverture, clôture, suspension, budget épuisé. |
| subsidy.deadline_changed | Tout ce qui relève de application_window : une échéance, la date d’ouverture, le dépôt continu, l’épuisement du budget. |
| subsidy.funding_changed | Tout ce qui relève de funding : taux, montants, plafonds, budget du programme. |
| subsidy.eligibility_changed | Tout ce qui relève de eligibility sauf les thèmes : types de demandeurs, tailles, secteurs, règles, types de coûts. |
| subsidy.updated | Tout le reste : titres, résumés, thèmes, liens, base légale. |
| subsidy.closing_soon | L’échéance d’une mesure ouverte est dans 14 jours, puis à nouveau dans 3 jours. Ce n’est pas une version : un passage horaire l’émet une fois par mesure, échéance et seuil. |
| subsidy.removed | La source ne liste plus la mesure. Elle n’apparaît plus dans les listes, sauf si vous passez include_withdrawn. |
| source.stale | Une source est passée de fresh ou delayed à stale, unavailable ou unreadable. |
| source.recovered | Elle est revenue. |
| match.created, match.status_changed, match.removed | Événements des listes de suivi, uniquement pour les webhooks du propriétaire. Voir listes de suivi. |
Le type principal d’une version est la catégorie la plus importante qu’elle touche, dans l’ordre statut, échéance, financement, éligibilité, mise à jour. Filtrez ou abonnez-vous sur une catégorie, pas seulement sur le type principal, sinon vous manquerez le changement d’échéance arrivé avec un changement de statut.
Différences par champ
fieldest un chemin pointé vers un champ terminal :status,application_window.closes_at,funding.amount_max,titles.nl. Les tableaux sont comparés en entier : une liste de régions modifiée est un seul changement, avec l’ancienne et la nouvelle liste.- La liste des règles est comparée règle par règle sur leurs id :
eligibility.rules[age_max]avec la règle avant et après (null si elle a été ajoutée ou retirée). Un changement de la seule provenance d’une règle, comme une nouvelle date de vérification, n’est pas un changement de la règle. - Les champs de gestion sont versionnés mais jamais signalés :
provenance.last_checked_at,provenance.content_hash,provenance.first_seen_atetprovenance.fields. Une version qui ne diffère que par ces champs ne produit aucun événement.
Dates dépassées
Chaque heure, nous normalisons à nouveau chaque fiche en vigueur par rapport à l’heure actuelle. Un appel dont l’échéance est passée devient closed, un appel annoncé qui s’est ouvert devient open, et closes_at passe à l’échéance suivante d’un appel en plusieurs phases. Chacun de ces changements est une nouvelle version, de cause date_passed, avec un événement ordinaire, en général subsidy.status_changed ou subsidy.deadline_changed. Le même passage horaire émet subsidy.closing_soon.
Suivre le flux
Faites le premier appel avec since (ou sans, à partir du plus ancien événement conservé), puis suivez next_cursor. Chaque page en a un, la dernière comprise : quand has_more vaut false, vous êtes à jour, et ce même curseur est le point de départ de la prochaine interrogation. Enregistrez-le avec le travail qu’il couvre : un redémarrage reprend exactement là où il s’était arrêté.
Rien n’est sauté ni répété, même si une importation valide de nombreux événements à la fois et que des importations peuvent se chevaucher : un événement ne reçoit sa place dans le flux (son seq) qu’une fois validé, de sorte qu’un événement validé tard arrive après tout ce que vous avez déjà lu. Ni fenêtre de chevauchement ni liste d’id déjà vus ne sont nécessaires. seq donne l’ordre du flux ; occurred_at est le moment où le changement a été constaté, et peut être un peu plus ancien que celui d’un événement précédent.
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
}
}Ou laissez-nous vous prévenir
Versions et historique
À partir de ProLes versions et as_of demandent les fonctions history et as_of.
GET /v1/subsidies/{id}/versions liste les versions d’une mesure, de la plus récente à la plus ancienne : { version, valid_from, valid_to, cause, content_hash, changes }. GET /v1/subsidies/{id}/versions/{version} renvoie la fiche telle qu’elle était, et GET /v1/subsidies/{id}?as_of= la version en vigueur à un instant donné. Des exemples figurent dans Rechercher des mesures.
Pourquoi une version a été écrite
| cause | Signification |
|---|---|
| source_change | La source a publié quelque chose de différent. |
| date_passed | Le passage horaire : une échéance ou une date d’ouverture est passée. |
| reprocess | Nous avons normalisé à nouveau la dernière lecture de la source, après une correction de la façon de la lire. |
| withdrawn | La source ne liste plus la mesure (cela émet subsidy.removed). |
| closed_at_source | La source ne la liste plus, et pour cette source un élément absent signifie que l’appel est clos. |
| restored | Une mesure que la source ne listait plus est de retour. |
| curation, merge | Réservé à une correction manuelle et à la fusion de deux fiches en une. Les anciens id d’une fiche fusionnée restent valides ; voir merged_from. |
Avec les versions et le flux, « qu’est-ce qui est ouvert ? » devient aussi « qu’est-ce qui a changé, quand, et que savait-on le jour de notre conseil ? ». Voir les tarifs.
