Skip to main content

CLI and Python API to fetch air quality index (AQI) data from the Montreal open data portal

Project description

AQI monitoring for the city of Montréal (Québec, Canada)

Latest Release Python CI PyPI Downloads License

A Python library and CLI tool to fetch, process, and expose air quality index (AQI) data from the City of Montréal open data platform.

The project is designed to be:

  • scriptable (JSON output by default)
  • embeddable as a Python library
  • suitable for automation (Home Assistant, cron jobs, data pipelines)

Features

  • Fetches the latest air quality data from Montréal’s open data portal
  • Lists currently active air quality monitoring stations
  • Computes the AQI based on RSQA methodology
  • Estimates pollutant concentrations from reported AQI contributions¹
  • Exposes structured station and pollutant data via Python models
  • Outputs machine-readable JSON from the CLI
  • Structured logging with optional debug mode
  • Test suite covering core logic, JSON contract, and CLI behavior

¹ Estimated concentrations are derived from rounded AQI values and should be treated as approximations.


Requirements

  • Python 3.11 or newer
  • requests

Installation

From PyPI (recommended)

pip install montreal-aqi-api

From source

git clone https://github.com/normcyr/montreal-aqi-api.git
cd montreal-aqi-api
python3 -m venv venv
source venv/bin/activate
pip install .

CLI Usage

The CLI always outputs JSON on stdout. Logs and diagnostics are written to stderr.

Fetch AQI for a specific station

montreal-aqi --station <station_id>

List available monitoring stations

montreal-aqi --list

Enable debug logging

montreal-aqi --station <station_id> --debug

Print the JSON in a pretty format

montreal-aqi --station <station_id> --pretty

or

montreal-aqi --list --pretty

No arguments

If no arguments are provided, the CLI returns a JSON error payload. Interactive prompts are intentionally avoided to keep behavior predictable in automated environments.

Advanced examples

Fetch multiple stations

montreal-aqi --station 1,2,3 --pretty

Suppress output (for scripts)

montreal-aqi --station 80 --quiet
# No output if successful, useful for cron jobs

Verbose logging

montreal-aqi --station 80 --verbose
# Shows detailed logs including API request times and cache status

Combine options

montreal-aqi --list --pretty --verbose

Integrations

This library is designed to be consumed by automated systems and integrations.

Home Assistant

Used by the custom Home Assistant integration:

Other Use Cases

  • Cron jobs
  • Data ingestion pipelines
  • Monitoring dashboards
  • Research / environmental analysis

JSON Contract — Version 1 (Frozen)

As of v0.4.0, the JSON output contract is explicitly versioned and frozen. The output format is formally specified in: docs/json_contract_v1.md.

The JSON output is governed by the official JSON Schema v1 and all payloads include:

{
  "version": 1,
  "type": "..."
}

Error Payload

{
  "version": 1,
  "type": "error",
  "error": {
    "code": "NO_DATA",
    "message": "No data available for this station"
  }
}

Stations List Payload

{
  "version": 1,
  "type": "stations",
  "stations": [
    {
      "station_id": "3",
      "name": "Saint-Jean-Baptiste",
      "borough": "Rivière-des-Prairies"
    }
  ]
}

Station AQI Payload

{
  "version": 1,
  "type": "station",
  "station_id": "80",
  "date": "2025-08-08",
  "hour": 10,
  "aqi": 49,
  "dominant_pollutant": "PM2.5",
  "pollutants": {
    "PM2.5": {
      "name": "PM2.5",
      "aqi": 49,
      "concentration": 34.3
    },
    "O3": {
      "name": "O3",
      "aqi": 22,
      "concentration": 70.4
    }
  }
}

Python Usage

from montreal_aqi_api.service import get_station_aqi

station = get_station_aqi("80")
if station:
    print(station.to_dict())

Domain objects (Station, Pollutant) expose explicit serialization helpers to ease downstream usage.


Exit codes

The montreal-aqi CLI exits with explicit status codes to make it suitable for scripting, automation, and CI pipelines.

Exit code Meaning Description
0 Success Command executed successfully
1 Generic API error An unexpected internal API error occurred
2 API unreachable Montreal Open Data API could not be reached (network error, timeout, DNS, etc.)
3 Invalid API response API returned malformed or unexpected JSON payload

Details

  • All errors are reported both via:
    • a structured JSON error payload on stdout
    • a non-zero process exit code
  • This ensures compatibility with:
    • shell scripts
    • cron jobs
    • CI/CD pipelines
    • Home Assistant / automation tools

Example

$ montreal-aqi --station 80
{
  "version": "1",
  "type": "error",
  "error": {
    "code": "API_UNREACHABLE",
    "message": "Montreal open data API is unreachable"
  }
}

$ echo $?
2

AQI Methodology

AQI values follow the methodology defined by the Réseau de surveillance de la qualité de l’air (RSQA).

Reference Values

Pollutant Full Name Reference
SO₂ Sulfur Dioxide 500 µg/m³
CO Carbon Monoxide 35 mg/m³
O₃ Ozone 160 µg/m³
NO₂ Nitrogen Dioxide 400 µg/m³
PM2.5 Particulate Matter 35 µg/m³

Project Status

  • JSON contract v1 frozen and validated by tests
  • Suitable for automation and integration
  • API stability guaranteed within v1

Contributing

Contributions are welcome.

Please ensure that:

  • tests pass (pytest)
  • the JSON contract remains backward compatible
  • any change affecting output is covered by tests
  • code is linted/formatted with ruff (run ruff format --check . and ruff check .)

Open an issue before proposing breaking changes.


Data Source

Data is retrieved from the Ville de Montréal Open Data Portal.


License

This project is licensed under the MIT License.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

montreal_aqi_api-0.5.0.tar.gz (17.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

montreal_aqi_api-0.5.0-py3-none-any.whl (14.2 kB view details)

Uploaded Python 3

File details

Details for the file montreal_aqi_api-0.5.0.tar.gz.

File metadata

  • Download URL: montreal_aqi_api-0.5.0.tar.gz
  • Upload date:
  • Size: 17.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.14

File hashes

Hashes for montreal_aqi_api-0.5.0.tar.gz
Algorithm Hash digest
SHA256 2ba7bd7e98fca8e6d160b30b6ca6116b7db3ee7ec09d7913ef73808a00c47980
MD5 7fe237823e98530c859913daba51fe15
BLAKE2b-256 dfeb57b0e3a025de86a7f4c46766390aa6007e5ad2bfc828f2a061999bc4e99b

See more details on using hashes here.

File details

Details for the file montreal_aqi_api-0.5.0-py3-none-any.whl.

File metadata

File hashes

Hashes for montreal_aqi_api-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a464794b407a0086ed8ecdc2fb101c964c31685fc8f287f13a37c4f37e046240
MD5 9c5a73e0224686b200fcbdb306a5e9c9
BLAKE2b-256 5cdbe8f71fdafb236e8f0f03a734ccaf36bfb796bc619bf6fb117408dee50057

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page