← Developers

The stadiq command.

One binary, no dependencies beyond Node 20, wrapping the four API endpoints. Readable output by default, --json when something downstream needs to parse it. Built for the case where the answer belongs in a shell script or a cron job rather than on a dashboard.

Install

shell
npm install -g stadiq
stadiq --help

Node 20 or newer. The package is dependency-free — it uses Node's built-in fetch and a hand-rolled flag parser — so the install is a single file and nothing is pulled in transitively.

Getting and storing a key

shell
# 1. Ask for a key. The link lands in your inbox; opening it creates the key.
stadiq signup you@company.be

# 2. Store it. Written to ~/.stadiq/config.json with mode 0600.
stadiq login sq_live_…

# 3. Confirm which key and host are in play.
stadiq whoami

signup posts to the same public endpoint as the web form, so you never have to open a browser except to click the link. Existing Stadiq customers can skip it and mint a key under Settings → API, or on the developer portal.

The key is resolved in this order, first match wins: --key, then the STADIQ_API_KEY environment variable, then ~/.stadiq/config.json. Prefer the environment variable in CI and in cron; prefer the config file on your own machine, where the 0600 file is a better place for a secret than a shell history line.

Commands

stadiq signup <email>
Email yourself a link that creates an API key.
stadiq login <key>
Store a key in ~/.stadiq/config.json.
stadiq whoami
Show the key prefix and base URL currently in use.
stadiq locations
The locations on your account, with their ids. Needs no target.
stadiq disruptions
Road works within 2 km, plus transit disruptions affecting the point.
stadiq air-quality
Nearest station reading, WHO and EU comparison, LEZ status.
stadiq briefing
Risk level, key facts, best and worst windows in the next 24 hours.
stadiq version
Print the version.

Flags

--lat <n> --lng <n>
Any point inside Flanders or Brussels. Required by the three location-scoped commands unless --location is given.
--location <id>
One of your saved locations, from stadiq locations. Mutually exclusive with lat/lng.
--json
Raw JSON instead of the readable summary. What you want in a pipeline.
--key <key>
Use this key for one invocation instead of the stored one.
--base <url>
Point at another host. Also settable as STADIQ_BASE_URL.
-h, --help
Usage.

Target validation happens before the request goes out, so a missing or non-numeric --lat fails locally rather than spending a call against your quota.

Output and quota

shell
# Any point in Flanders or Brussels.
stadiq disruptions --lat 51.2194 --lng 4.4025

# One of your own saved locations.
stadiq air-quality --location <id>

# Raw JSON, for piping.
stadiq briefing --lat 51.2194 --lng 4.4025 --json | jq '.briefing.risk'

Without --json the CLI prints a short summary and then the number of calls left today, read from the X-RateLimit-Remaining header the API sets on every response. With --json it prints the response body and nothing else, so the output stays parseable.

On an API error the CLI writes the status, error code and the API's own message to stderr and exits non-zero. That last part matters in scripts: a 401 and a genuinely quiet street both produce very little stdout, and only the exit code tells them apart.

In a cron job

check-disruptions.sh
#!/bin/sh
# Alert if a high-severity transit disruption appears near the shop.
# Runs from cron; the key comes from the environment, not from a config file
# the cron user may not be able to read.
export STADIQ_API_KEY="sq_live_…"

count=$(stadiq disruptions --lat 51.2194 --lng 4.4025 --json \
  | jq '.summary.highSeverityTransit')

# The CLI exits non-zero on an API error, so "set -e" or an explicit check
# stops this reporting "0 disruptions" when what happened was a 401.
[ "$count" -gt 0 ] && printf 'transit disruption near the shop: %s\n' "$count"

Bear the quota in mind when you pick an interval. The free developer tier is 100 calls a day, which is one call every fifteen minutes with room to spare — and the upstream data does not move faster than that. API responses are cacheable for 60 seconds, so polling faster mostly buys you the same bytes twice.

Where the details are

The response bodies the CLI prints under --jsonare the API's, unchanged. Field-by-field descriptions, error codes and plan quotas are on the API reference. If you would rather an agent called these endpoints than a shell script, there is an MCP server with the same four tools.

  • GIPODEvery permitted road work and public-domain occupation in Flanders, over an open OGC API Features service that needs no key.
  • IRCELINE air qualityBelgium's official air-quality measurements, over a 52°North SOS timeseries API. Open, and stranger than it looks.
  • De Lijn realtimeDetours and stop data for Flemish public transport, and which of De Lijn's API products actually carries what.
  • Antwerp open dataWhat the city of Antwerp publishes, where the ArcGIS endpoints are, and how to query them as GeoJSON.
  • Stadiq MCP serverThe same four endpoints as read-only agent tools, for Claude Desktop, Cursor or any MCP client.