Aller au contenu
Subsido

Utiliser l'API

Pagination

Les listes se paginent avec un curseur opaque, jamais avec un décalage : la page deux mille coûte autant que la première, et aucune ligne n’est sautée ni répétée quand les données bougent entre-temps.

L’enveloppe

Une liste paginée répond :

{
  "data": [
    "…"
  ],
  "pagination": {
    "has_more": true,
    "next_cursor": "eyJzIjoic3Vic2lkaWVzOnVwZGF0ZWQiLCJrIjoi…",
    "limit": 50
  },
  "meta": {
    "request_id": "req_…",
    "warnings": []
  }
}
  • has_more est un fait, pas une supposition : l’API lit une ligne de plus que demandé. Il n’y a pas de total.
  • next_cursor n’est présent que si has_more vaut true. Renvoyez-le comme cursor, avec les mêmes paramètres, pour la page suivante. Le flux de modifications fait exception : il renvoie un curseur sur chaque page, la dernière comprise, pour que vous puissiez reprendre à partir de là (voir suivre le flux).
  • limit est la taille de page utilisée.
curl "https://api.subsido.be/v1/subsidies?status=open&sort=updated&limit=100&cursor=eyJzIjoic3Vic2lkaWVzOnVwZGF0ZWQiLCJrIjoi…" \  -H "Authorization: Bearer sb_live_..."

Tailles de page

limit vaut 50 par défaut. Au-delà du maximum de votre formule, c’est une erreur, 400 invalid_parameter, jamais une troncature silencieuse : servir discrètement 20 lignes à qui en demandait 100, c’est lui faire croire qu’il a lu toute une liste alors qu’il n’en a lu que la première page.

Formulelimit maximale
Developer100
Pro, Business200
Enterprise500

Les mêmes chiffres figurent dans max_page_size de GET /v1/plans et de GET /v1/key. La clé d’un compte sans formule reçoit 402 subscription_required sur chaque liste, quelle que soit la limite.

Curseurs

  • Un curseur contient la clé de tri et l’id de la dernière ligne. Traitez-le comme opaque : son format peut changer.
  • Un curseur appartient à la liste et à l’ordre de tri dont il provient. Réutilisé ailleurs (un autre sort, une autre route), il donne 400 invalid_cursor, et vous recommencez sans curseur ; l’API ne repart jamais discrètement de la première page.
  • Gardez les mêmes filtres pendant la pagination. Le curseur ne les mémorise pas : les changer en cours de route vous fait parcourir une autre liste à partir de l’endroit où l’ancienne s’était arrêtée.
  • Une page à la fois. Des requêtes parallèles n’accélèrent pas le parcours d’un curseur et consomment votre limite par seconde.

Ordres de tri

ListeOrdre
GET /v1/subsidiessort=relevance (meilleure correspondance textuelle ; par défaut avec q), deadline (échéance la plus proche d’abord, sans échéance à la fin ; par défaut sans q), updated (dernière modification d’abord) ou title. Sans q exploitable, relevance se rabat sur updated.
GET /v1/changesDu plus ancien au plus récent, par seq. Voir suivre le flux.
GET /v1/watchlists/{id}/companiesPar référence.
GET /v1/webhooksDu plus ancien au plus récent.

Quelles listes sont paginées

RoutePagination
GET /v1/subsidies, /v1/changes, /v1/watchlists/{id}/companies, /v1/webhookslimit et cursor, comme ci-dessus.
GET /v1/watchlistsToutes les listes de suivi en une page (50 au plus) ; has_more vaut toujours false.
GET /v1/watchlists/{id}/matchesPas de curseur : limit de 1 à 5 000 (500 par défaut), filtrable par entreprise.
GET /v1/subsidies/{id}/versionsToutes les versions en une réponse, de la plus récente à la plus ancienne.
GET /v1/sourcesToutes les sources en une réponse.
GET /v1/webhooks/{id}/deliveriesLes 50 dernières.
GET /v1/export/subsidies.ndjsonTout le catalogue en un seul téléchargement en flux (à partir de Business).

Parcourir toute une liste

Python
import os, requests

def all_open_measures():
    params = {"status": "open,continuous,forthcoming", "sort": "updated", "limit": 100}
    headers = {"Authorization": f"Bearer {os.environ['SUBSIDY_API_KEY']}"}
    while True:
        r = requests.get("https://api.subsido.be/v1/subsidies", params=params, headers=headers, timeout=30)
        r.raise_for_status()
        page = r.json()
        yield from page["data"]
        if not page["pagination"]["has_more"]:
            return
        params["cursor"] = page["pagination"]["next_cursor"]

Chaque ligne, à chaque fois

Chaque champ de chaque ligne est présent sur chaque page, null quand il ne s’applique pas : une ligne a les mêmes clés en page un et en page quatre cents. Pour tout le catalogue d’un coup, l’export revient moins cher que la pagination.