Retrieve air quality data from the Clarity.io API
Project description
clarityio
This package wraps the API for Clarity air quality sensors. It makes calls to v2 of the API, which as of June 2026 is the newest version of the API.
Development status
This package is stable and used in production at the City of Ann Arbor.
Implemented endpoints
- Recent measurements:
POST {baseUrl}/v2/recent-datasource-measurements-query - Recent measurements continuation:
POST {baseUrl}/v2/recent-datasource-measurements-continuation - Historical measurements:
POST {baseUrl}/v2/report-requests - Per-Org Datasources summary:
GET {baseUrl}/v2/datasources - Per-Datasource details:
GET {baseUrl}/v2/datasources/:datasourceId
Not yet implemented
- Devices / nodes:
GET {baseUrl}/v2/devices/nodesand per-node detail/status - Subscriptions:
GET {baseUrl}/v2/subscriptions - Metrics dictionary and other reference endpoints
Installation
Install from PyPI:
pip install clarityio
Usage
Initialize API connection
Find your API key and org in your Clarity.io user profile. Log in at https://dashboard.clarity.io, then click the person icon on the top-right corner.
Use these values to initialize a connection:
import clarityio
import pandas as pd
api_connection = clarityio.ClarityAPIConnection(api_key='YOUR_API_KEY', org='YOUR_ORG')
Both of these values are required to make calls to the Clarity API and are appended as needed by this package.
Retrieve recent measurements
The API limits how far back this endpoint can look (e.g., 48 hours for hourly data). For older data or bounded time windows, use get_historical_measurements() instead.
The default format is json-long, which returns one row per combination of metric and time:
response = api_connection.get_recent_measurements(
all_datasources=True,
output_frequency='hour',
start_time='2024-07-22T00:00:00Z',
)
df = pd.DataFrame(response['data'])
To get wide format (one row per timestamp, each metric in its own column):
from io import StringIO
response_wide = api_connection.get_recent_measurements(
all_datasources=True,
output_frequency='hour',
format='csv-wide',
metric_select='only pm2_5ConcMass24HourRollingMean', # see API docs for metric selection
)
df_wide = pd.read_csv(StringIO(response_wide))
Stream new measurements with a continuation token
To poll for new data without time-based race conditions, seed a continuation token and pass it back on each subsequent call. Each call returns only data that arrived since the previous one. Tokens are valid for 24 hours.
import time
# Seed a token from an initial recent-measurements call
data, token = api_connection.get_recent_measurements(
datasource_ids=['A_DATA_SOURCE_ID'],
reply_with_continuation_token=True,
)
# On each poll, pass the latest token to get only new data
while True:
time.sleep(60)
data, token = api_connection.get_measurements_continuation(token)
if data:
... # process new measurements
Retrieve historical measurements
Use this for arbitrary date ranges or data older than the recent-measurements lookback limits. The method submits an async report, polls until ready, and returns a wide-format DataFrame. Note that the API allows 30 reports per org per day.
df = api_connection.get_historical_measurements(
start_time='2024-01-01T00:00:00Z',
end_time='2024-01-31T00:00:00Z',
all_datasources=True,
output_frequency='hour',
)
The returned DataFrame has one row per datasource/time-period. The timestamp column is startOfPeriod and metric columns follow the pattern {metricName}.value (e.g. pm2_5ConcMass1HourMean.value).
List data sources
datasources_response = api_connection.get_datasources()
datasources = pd.json_normalize(datasources_response['datasources'])
Get details for a specific data source
Obtain the IDs from the prior block of code.
source_details_response = api_connection.get_datasource_details('A_DATA_SOURCE_ID')
source_details = pd.json_normalize(source_details_response['datasource'])
Convert a raw measurement to the EPA AQI scale
The Clarity API provides some of these values, but this utility function offers more flexibility for custom data processing.
clarityio.scale_raw_to_aqi('pm2.5_24hr', 18.84) # 69.14676806083651
clarityio.scale_raw_to_aqi('nitrogen_dioxide_1hr', 300) # 138.64864864864865
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file clarityio-1.1.0.tar.gz.
File metadata
- Download URL: clarityio-1.1.0.tar.gz
- Upload date:
- Size: 15.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
12b528c7d68b7e94dc07d839c3dc105eccb44ddfaa9e45f899bbac69652fd245
|
|
| MD5 |
15cafd634c0b92997fca73c337c71fc5
|
|
| BLAKE2b-256 |
44a40ffd1d9802552cc4d68c57a8642d702ad0eb0e88b149dccc3be4c516158f
|
File details
Details for the file clarityio-1.1.0-py3-none-any.whl.
File metadata
- Download URL: clarityio-1.1.0-py3-none-any.whl
- Upload date:
- Size: 9.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b93da42b234bf7ed2ccf4680fef0354c20c5dc2ed72f87897663e30d06922ce7
|
|
| MD5 |
38f9fa8cb567904921bf01e2025ef984
|
|
| BLAKE2b-256 |
80612674c6a35edb4326794f6bc139ada65ee9ec718d632f02262da751be71d4
|