Skip to content
Subsido

Start

Authentication

Bearer keys, live and test keys, the routes that answer without one, and checking a key.

Bearer keys

Send your key on every request to a keyed route, as a bearer token in the Authorization header.

curl "https://api.subsido.be/v1/subsidies?limit=3" \  -H "Authorization: Bearer sb_live_..."
  • X-API-Key: sb_live_... works too, for tools that cannot set an Authorization header. When both are sent, Authorization wins.
  • The scheme is case-insensitive (Bearer or bearer), and a key sent in Authorization without the scheme is accepted as well.
  • A missing, malformed or revoked key is 401 unauthorized. The response does not say which of the three, so that someone guessing keys learns nothing from it.
  • A valid key on an account without a plan is 402 subscription_required until a plan is chosen.
  • The MCP endpoint, POST /mcp, takes the same key in the same header.

Live and test keys

A key is minted as sb_live_… or sb_test_…. Both reach exactly the same data and both are metered the same way, against your monthly quota, your match evaluations and your rate limit. The label is yours: use test keys for CI and local development so their usage is told apart from production’s in the dashboard.

The number of keys an account may hold depends on the plan (see pricing). A key is shown once, when it is created. Only its SHA-256 hash and its first characters are stored, so there is no endpoint that can return a secret: a lost key is revoked in the dashboard and replaced. Revoking takes effect immediately.

Keep keys on the server

A key in browser JavaScript is a key anyone can copy and spend. Call the API from your backend, and give your front end only what it needs to render.

Checking a key

GET /v1/key answers with the calling key’s plan, everything the plan allows, and this month’s usage, the request being made included. It is the right first request for a new integration and a good health check for a running one. Like every other route, the answer is wrapped in data, with meta beside it.

curl "https://api.subsido.be/v1/key" -H "Authorization: Bearer sb_live_..."
{
  "data": {
    "live": true,
    "plan": {
      "plan": "developer",
      "label": "Developer",
      "price_monthly_eur": 20,
      "price_yearly_eur": 200,
      "price_from_monthly_eur": null,
      "self_serve": true,
      "purchasable": true,
      "monthly_requests": 10000,
      "monthly_match_evaluations": 100,
      "rate_limit_rps": 5,
      "api_keys": 2,
      "max_page_size": 100,
      "max_bulk_companies": 0,
      "watchlist_companies": 0,
      "webhook_endpoints": 0,
      "capabilities": {
        "change_feed": true,
        "history": false,
        "as_of": false,
        "webhooks": false,
        "bulk_match": false,
        "watchlists": false,
        "bulk_export": false,
        "redistribution_rights": false
      }
    },
    "requests_this_month": 1284,
    "match_evaluations_this_month": 37
  },
  "meta": {
    "request_id": "req_01hxyz",
    "warnings": []
  }
}

Routes that need no key

These publish what the website prints anyway. They are rate limited per client address, carry no RateLimit-* headers, and do not count against any quota.

RouteWhat it is for
GET /v1/healthStatus, version, and which sources are not fresh.
GET /v1/plansPlans, prices and everything each allows.
GET /v1/openapi.jsonThe OpenAPI 3.1 contract.
GET /v1/taxonomyEvery closed vocabulary with Dutch, French and English labels, the rule fields and operators, the event types.
GET /v1/coverageHow many measures there are, by status, source, instrument, level, region and topic.
GET /v1/sourcesEvery source, its licence and rights mode, and its freshness.
GET /v1/sources/{id}One source, with its last ten ingestion runs.

Everything else, the MCP endpoint included, needs a key. A route that needs one answers 401 without it; see errors.

Headers on every response

HeaderMeaning
X-Request-IdThe request’s id (req_…), also in meta.request_id or error.request_id. Quote it when you write to us.
X-IndependenceThe independence statement: an independent service, not a public authority. Machines can read it without reading the website.
RateLimit-Limit, RateLimit-Remaining, RateLimit-ResetOn keyed routes: your monthly request quota, what is left, and the seconds until it resets. See rate limits.
X-Quota-Limit, X-Quota-RemainingThe same monthly figures under a second name.