airqosm
airqosm is a lightweight Python client for the AirQo source metadata API. Given a latitude and longitude, it returns ranked likely pollution sources together with the geographic and Sentinel-2 evidence used by the API.
Requirements
- Python 3.9 or newer
- An AirQo API token
Installation
pip install airqosm
From this repository:
cd packages/airqo-source-metadata
pip install -e .
Install the optional local proxy server:
pip install "airqosm[api]"
Authentication
Pass a token directly or set AIRQO_PLATFORM_TOKEN or AIRQO_API_TOKEN.
$env:AIRQO_API_TOKEN = "your-airqo-api-token"
Tokens can be generated from the API section of your AirQo Analytics account at https://analytics.airqo.net/.
Quick start
import airqosm
response = airqosm.source_metadata(
latitude=0.230918,
longitude=32.614595,
include_satellite=True,
)
print(response["data"]["primary_source"])
print(response["data"]["candidate_sources"])
print(response["data"]["evidence"]["sentinel2_context"])
A token may also be passed explicitly:
from airqosm import SourceMetadataClient
client = SourceMetadataClient(token="your-airqo-api-token", timeout=30)
response = client.fetch(
latitude=0.230918,
longitude=32.614595,
include_satellite=True,
)
Convenience helpers return only one part of the response:
from airqosm import candidate_sources, primary_source
primary = primary_source(0.230918, 32.614595, include_satellite=False)
candidates = candidate_sources(0.230918, 32.614595)
Response format
The platform may wrap a single result in one or more singleton arrays. The client removes those wrappers and always returns a dictionary with message and data:
{
"message": "Operation successful",
"data": {
"location": {
"area_name": "Munyonyo",
"latitude": 0.230918,
"longitude": 32.614595
},
"primary_source": {
"source_type": "traffic",
"confidence": 0.3478
},
"candidate_sources": [
{"source_type": "traffic", "confidence": 0.3478},
{"source_type": "mixed_urban", "confidence": 0.3478},
{"source_type": "biomass_burning", "confidence": 0.1739}
],
"evidence": {
"site_category": {
"category": "Urban Background",
"classification_confidence": 0.65,
"classification_method": "nominatim",
"highway": "residential"
},
"reasoning": [
"The point is in a built-up urban or residential context.",
"Road type 'residential' supports local traffic influence."
],
"sentinel2_context": {
"provider": "Element 84 Earth Search",
"collection": "sentinel-2-l2a",
"indices": {
"ndvi": 0.7655,
"ndbi": -0.2435,
"ndwi": -0.6834,
"bare_soil_index": -0.2025,
"normalized_burn_ratio": 0.5337
}
},
"sentinel2_error": null
},
"metadata": {
"model_version": "2.0.0",
"satellite_data_used": true,
"cache_hit": false
}
}
}
Treat source attribution as contextual evidence, not direct emissions measurement. The API disclaimer and reasoning fields should be retained when results are shown to end users.
Satellite context
include_satellite=True requests free Copernicus Sentinel-2 L2A land-surface context through Element 84 Earth Search. It adds vegetation, built-up, water, bare-soil, and burn-ratio indices.
Set include_satellite=False for a faster OSM/site-category-only request.
Optional query parameters
Additional platform query parameters can be supplied without allowing core request fields to be overwritten:
response = client.fetch(
latitude=0.230918,
longitude=32.614595,
extra_params={"start_date": "2026-04-23", "end_date": "2026-06-22"},
)
extra_params cannot replace latitude, longitude, include_satellite, or token.
Errors
Invalid coordinates and configuration raise ValueError. Network, HTTP, invalid JSON, and malformed platform responses raise SourceMetadataClientError:
from airqosm import SourceMetadataClientError, source_metadata
try:
response = source_metadata(0.230918, 32.614595)
except SourceMetadataClientError as error:
print(error.status_code)
print(error.payload)
Optional proxy API
Run a local proxy backed by the AirQo platform:
airqosm-api --host 0.0.0.0 --port 8010 --platform-token your-airqo-api-token
Endpoints:
GET /healthzGET /api/v2/spatial/source_metadata
curl "http://127.0.0.1:8010/api/v2/spatial/source_metadata?latitude=0.230918&longitude=32.614595&include_satellite=true"
If --platform-token is omitted, callers must provide Authorization: Bearer <token> or a token query parameter.
Development
cd packages/airqo-source-metadata
python -m unittest discover -s tests -v
python -m build
python -m twine check dist/*
License
MIT
Metadata
Release files for airqosm 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| airqosm-0.3.0.tar.gz | 11.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| airqosm-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 24.4 kB
Release files / airqosm-0.3.0.tar.gz
| Download URL | airqosm-0.3.0.tar.gz |
|---|---|
| Size | 11.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1a047aaa6e0d376e679260a065851572ef83a59ff2e082190887312b548b35c1
|
|
BLAKE2b-256 checksum How to use checksums |
bcdca1cfde346682af2b0bd6b533142379ed2f9c334b825eac8e190a68f988d3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.10.11
|
Release files / airqosm-0.3.0-py3-none-any.whl
| Download URL | airqosm-0.3.0-py3-none-any.whl |
|---|---|
| Size | 12.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3964a5d3d855f94f7a4084568a91dfcbf93bf3f8f13e1a2aa5640b6cb44ea654
|
|
BLAKE2b-256 checksum How to use checksums |
9835d296ff05ae94289a65044e1cc5c1ac3a7b89d73cc6ba5ffaa4b6373d0ab8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.10.11
|